blob: b163899f597097982ea500accc19844c54d4676e [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;
Marc Schink137f02f2020-08-23 16:19:44 +020057static bool enable_target_power;
Marc Schink3578ec62016-03-17 16:23:03 +010058
59static bool assert_cs(void)
60{
61 int ret;
62
63 if (reset_cs) {
64 ret = jaylink_clear_reset(jaylink_devh);
65
66 if (ret != JAYLINK_OK) {
67 msg_perr("jaylink_clear_reset() failed: %s.\n", jaylink_strerror(ret));
68 return false;
69 }
70 } else {
71 ret = jaylink_jtag_clear_trst(jaylink_devh);
72
73 if (ret != JAYLINK_OK) {
74 msg_perr("jaylink_jtag_clear_trst() failed: %s.\n", jaylink_strerror(ret));
75 return false;
76 }
77 }
78
79 return true;
80}
81
82static bool deassert_cs(void)
83{
84 int ret;
85
86 if (reset_cs) {
87 ret = jaylink_set_reset(jaylink_devh);
88
89 if (ret != JAYLINK_OK) {
90 msg_perr("jaylink_set_reset() failed: %s.\n", jaylink_strerror(ret));
91 return false;
92 }
93 } else {
94 ret = jaylink_jtag_set_trst(jaylink_devh);
95
96 if (ret != JAYLINK_OK) {
97 msg_perr("jaylink_jtag_set_trst() failed: %s.\n", jaylink_strerror(ret));
98 return false;
99 }
100 }
101
102 return true;
103}
104
Edward O'Callaghan5eca4272020-04-12 17:27:53 +1000105static int jlink_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
Marc Schink3578ec62016-03-17 16:23:03 +0100106 const unsigned char *writearr, unsigned char *readarr)
107{
108 uint32_t length;
109 uint8_t *buffer;
110
111 length = writecnt + readcnt;
112
113 if (length > JTAG_MAX_TRANSFER_SIZE)
114 return SPI_INVALID_LENGTH;
115
116 buffer = malloc(length);
117
118 if (!buffer) {
119 msg_perr("Memory allocation failed.\n");
120 return SPI_GENERIC_ERROR;
121 }
122
123 /* Reverse all bytes because the device transfers data LSB first. */
124 reverse_bytes(buffer, writearr, writecnt);
125
126 memset(buffer + writecnt, 0x00, readcnt);
127
128 if (!assert_cs()) {
129 free(buffer);
130 return SPI_PROGRAMMER_ERROR;
131 }
132
133 int ret;
134
135 ret = jaylink_jtag_io(jaylink_devh, buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2);
136
137 if (ret != JAYLINK_OK) {
Angel Pons281ed262021-04-16 10:55:03 +0200138 msg_perr("jaylink_jtag_io() failed: %s.\n", jaylink_strerror(ret));
Marc Schink3578ec62016-03-17 16:23:03 +0100139 free(buffer);
140 return SPI_PROGRAMMER_ERROR;
141 }
142
143 if (!deassert_cs()) {
144 free(buffer);
145 return SPI_PROGRAMMER_ERROR;
146 }
147
148 /* Reverse all bytes because the device transfers data LSB first. */
149 reverse_bytes(readarr, buffer + writecnt, readcnt);
150 free(buffer);
151
152 return 0;
153}
154
155static const struct spi_master spi_master_jlink_spi = {
Marc Schink3578ec62016-03-17 16:23:03 +0100156 /* Maximum data read size in one go (excluding opcode+address). */
157 .max_data_read = JTAG_MAX_TRANSFER_SIZE - 5,
158 /* Maximum data write size in one go (excluding opcode+address). */
159 .max_data_write = JTAG_MAX_TRANSFER_SIZE - 5,
160 .command = jlink_spi_send_command,
161 .multicommand = default_spi_send_multicommand,
162 .read = default_spi_read,
163 .write_256 = default_spi_write_256,
164 .write_aai = default_spi_write_aai,
165 .features = SPI_MASTER_4BA,
166};
167
168static int jlink_spi_shutdown(void *data)
169{
Marc Schink137f02f2020-08-23 16:19:44 +0200170 if (jaylink_devh) {
171 if (enable_target_power) {
172 int ret = jaylink_set_target_power(jaylink_devh, false);
173
174 if (ret != JAYLINK_OK) {
175 msg_perr("jaylink_set_target_power() failed: %s.\n",
176 jaylink_strerror(ret));
177 }
178 }
179
Marc Schink3578ec62016-03-17 16:23:03 +0100180 jaylink_close(jaylink_devh);
Marc Schink137f02f2020-08-23 16:19:44 +0200181 }
Marc Schink3578ec62016-03-17 16:23:03 +0100182
183 jaylink_exit(jaylink_ctx);
Marc Schink3578ec62016-03-17 16:23:03 +0100184 return 0;
185}
186
Thomas Heijligencc853d82021-05-04 15:32:17 +0200187static int jlink_spi_init(void)
Marc Schink3578ec62016-03-17 16:23:03 +0100188{
189 char *arg;
190 unsigned long speed = 0;
191
Marc Schink3578ec62016-03-17 16:23:03 +0100192 arg = extract_programmer_param("spispeed");
193
194 if (arg) {
195 char *endptr;
196
197 errno = 0;
198 speed = strtoul(arg, &endptr, 10);
199
200 if (*endptr != '\0' || errno != 0) {
201 msg_perr("Invalid SPI speed specified: %s.\n", arg);
202 free(arg);
203 return 1;
204 }
205
206 if (speed < 1) {
207 msg_perr("SPI speed must be at least 1 kHz.\n");
208 free(arg);
209 return 1;
210 }
211 }
212
213 free(arg);
214
215 int ret;
216 bool use_serial_number;
217 uint32_t serial_number;
218
219 arg = extract_programmer_param("serial");
220
221 if (arg) {
222 if (!strlen(arg)) {
Angel Pons281ed262021-04-16 10:55:03 +0200223 msg_perr("Empty serial number specified.\n");
Marc Schink3578ec62016-03-17 16:23:03 +0100224 free(arg);
225 return 1;
226 }
227
228 ret = jaylink_parse_serial_number(arg, &serial_number);
229
230 if (ret == JAYLINK_ERR) {
231 msg_perr("Invalid serial number specified: %s.\n", arg);
232 free(arg);
233 return 1;
234 } if (ret != JAYLINK_OK) {
235 msg_perr("jaylink_parse_serial_number() failed: %s.\n", jaylink_strerror(ret));
236 free(arg);
237 return 1;
238 }
239
240 use_serial_number = true;
241 } else {
242 use_serial_number = false;
243 }
244
245 free(arg);
246
247 reset_cs = true;
248 arg = extract_programmer_param("cs");
249
250 if (arg) {
251 if (!strcasecmp(arg, "reset")) {
252 reset_cs = true;
253 } else if (!strcasecmp(arg, "trst")) {
254 reset_cs = false;
255 } else {
256 msg_perr("Invalid chip select pin specified: '%s'.\n", arg);
257 free(arg);
258 return 1;
259 }
260 }
261
262 free(arg);
263
264 if (reset_cs)
265 msg_pdbg("Using RESET as chip select signal.\n");
266 else
267 msg_pdbg("Using TRST as chip select signal.\n");
268
Marc Schink137f02f2020-08-23 16:19:44 +0200269 enable_target_power = false;
270 arg = extract_programmer_param("power");
271
272 if (arg) {
273 if (!strcasecmp(arg, "on")) {
274 enable_target_power = true;
275 } else {
276 msg_perr("Invalid value for 'power' argument: '%s'.\n", arg);
277 free(arg);
278 return 1;
279 }
280 }
281
282 free(arg);
283
Marc Schink3578ec62016-03-17 16:23:03 +0100284 ret = jaylink_init(&jaylink_ctx);
285
286 if (ret != JAYLINK_OK) {
287 msg_perr("jaylink_init() failed: %s.\n", jaylink_strerror(ret));
288 return 1;
289 }
290
291 ret = jaylink_discovery_scan(jaylink_ctx, 0);
292
293 if (ret != JAYLINK_OK) {
Angel Pons281ed262021-04-16 10:55:03 +0200294 msg_perr("jaylink_discovery_scan() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000295 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100296 }
297
298 struct jaylink_device **devs;
299
300 ret = jaylink_get_devices(jaylink_ctx, &devs, NULL);
301
302 if (ret != JAYLINK_OK) {
303 msg_perr("jaylink_get_devices() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000304 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100305 }
306
307 if (!use_serial_number)
308 msg_pdbg("No device selected, using first device.\n");
309
310 size_t i;
311 struct jaylink_device *dev;
312 bool device_found = false;
313
314 for (i = 0; devs[i]; i++) {
315 if (use_serial_number) {
316 uint32_t tmp;
317
318 ret = jaylink_device_get_serial_number(devs[i], &tmp);
319
320 if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
321 continue;
322 } else if (ret != JAYLINK_OK) {
323 msg_pwarn("jaylink_device_get_serial_number() failed: %s.\n",
324 jaylink_strerror(ret));
325 continue;
326 }
327
328 if (serial_number != tmp)
329 continue;
330 }
331
332 ret = jaylink_open(devs[i], &jaylink_devh);
333
334 if (ret == JAYLINK_OK) {
335 dev = devs[i];
336 device_found = true;
337 break;
338 }
339
340 jaylink_devh = NULL;
341 }
342
343 jaylink_free_devices(devs, true);
344
345 if (!device_found) {
346 msg_perr("No J-Link device found.\n");
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000347 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100348 }
349
350 size_t length;
351 char *firmware_version;
352
353 ret = jaylink_get_firmware_version(jaylink_devh, &firmware_version,
354 &length);
355
356 if (ret != JAYLINK_OK) {
357 msg_perr("jaylink_get_firmware_version() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000358 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100359 } else if (length > 0) {
360 msg_pdbg("Firmware: %s\n", firmware_version);
361 free(firmware_version);
362 }
363
364 ret = jaylink_device_get_serial_number(dev, &serial_number);
365
366 if (ret == JAYLINK_OK) {
367 msg_pdbg("S/N: %" PRIu32 "\n", serial_number);
368 } else if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
369 msg_pdbg("S/N: N/A\n");
370 } else {
371 msg_perr("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000372 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100373 }
374
Angel Pons7e134562021-06-07 13:29:13 +0200375 uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE] = { 0 };
Marc Schink3578ec62016-03-17 16:23:03 +0100376
Marc Schink3578ec62016-03-17 16:23:03 +0100377 ret = jaylink_get_caps(jaylink_devh, caps);
378
379 if (ret != JAYLINK_OK) {
380 msg_perr("jaylink_get_caps() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000381 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100382 }
383
384 if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
385 ret = jaylink_get_extended_caps(jaylink_devh, caps);
386
387 if (ret != JAYLINK_OK) {
Angel Pons281ed262021-04-16 10:55:03 +0200388 msg_perr("jaylink_get_extended_caps() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000389 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100390 }
391 }
392
Marc Schink137f02f2020-08-23 16:19:44 +0200393 if (enable_target_power) {
394 if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) {
395 msg_perr("Device does not support target power.\n");
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000396 goto init_err;
Marc Schink137f02f2020-08-23 16:19:44 +0200397 }
398 }
399
Marc Schink3578ec62016-03-17 16:23:03 +0100400 uint32_t ifaces;
401
402 ret = jaylink_get_available_interfaces(jaylink_devh, &ifaces);
403
404 if (ret != JAYLINK_OK) {
405 msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000406 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100407 }
408
409 if (!(ifaces & (1 << JAYLINK_TIF_JTAG))) {
410 msg_perr("Device does not support JTAG interface.\n");
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000411 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100412 }
413
414 ret = jaylink_select_interface(jaylink_devh, JAYLINK_TIF_JTAG, NULL);
415
416 if (ret != JAYLINK_OK) {
417 msg_perr("jaylink_select_interface() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000418 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100419 }
420
Marc Schink137f02f2020-08-23 16:19:44 +0200421 if (enable_target_power) {
422 ret = jaylink_set_target_power(jaylink_devh, true);
423
424 if (ret != JAYLINK_OK) {
425 msg_perr("jaylink_set_target_power() failed: %s.\n", jaylink_strerror(ret));
426 return 1;
427 }
428
429 /* Wait some time until the target is powered up. */
430 internal_sleep(10000);
431 }
432
Marc Schink3578ec62016-03-17 16:23:03 +0100433 struct jaylink_hardware_status hwstat;
434
435 ret = jaylink_get_hardware_status(jaylink_devh, &hwstat);
436
437 if (ret != JAYLINK_OK) {
438 msg_perr("jaylink_get_hardware_status() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000439 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100440 }
441
442 msg_pdbg("VTarget: %u.%03u V\n", hwstat.target_voltage / 1000,
443 hwstat.target_voltage % 1000);
444
445 if (hwstat.target_voltage < MIN_TARGET_VOLTAGE) {
446 msg_perr("Target voltage is below %u.%03u V. You need to attach VTref to the I/O voltage of "
447 "the chip.\n", MIN_TARGET_VOLTAGE / 1000, MIN_TARGET_VOLTAGE % 1000);
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000448 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100449 }
450
451 struct jaylink_speed device_speeds;
452
453 device_speeds.freq = DEFAULT_FREQ;
454 device_speeds.div = DEFAULT_FREQ_DIV;
455
456 if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
457 ret = jaylink_get_speeds(jaylink_devh, &device_speeds);
458
459 if (ret != JAYLINK_OK) {
460 msg_perr("jaylink_get_speeds() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000461 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100462 }
463 }
464
465 device_speeds.freq /= 1000;
466
467 msg_pdbg("Maximum SPI speed: %" PRIu32 " kHz\n", device_speeds.freq / device_speeds.div);
468
469 if (!speed) {
470 speed = device_speeds.freq / device_speeds.div;
471 msg_pdbg("SPI speed not specified, using %lu kHz.\n", speed);
472 }
473
474 if (speed > (device_speeds.freq / device_speeds.div)) {
475 msg_perr("Specified SPI speed of %lu kHz is too high. Maximum is %" PRIu32 " kHz.\n", speed,
476 device_speeds.freq / device_speeds.div);
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000477 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100478 }
479
480 ret = jaylink_set_speed(jaylink_devh, speed);
481
482 if (ret != JAYLINK_OK) {
483 msg_perr("jaylink_set_speed() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000484 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100485 }
486
487 msg_pdbg("SPI speed: %lu kHz\n", speed);
488
489 /* Ensure that the CS signal is not active initially. */
490 if (!deassert_cs())
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000491 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100492
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000493 if (register_shutdown(jlink_spi_shutdown, NULL))
494 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100495 register_spi_master(&spi_master_jlink_spi);
496
497 return 0;
Anastasia Klimchuk00c2e802021-04-14 09:52:36 +1000498
499init_err:
500 if (jaylink_devh)
501 jaylink_close(jaylink_devh);
502
503 jaylink_exit(jaylink_ctx);
504
505 return 1;
Marc Schink3578ec62016-03-17 16:23:03 +0100506}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200507
508const struct programmer_entry programmer_jlink_spi = {
509 .name = "jlink_spi",
510 .type = OTHER,
511 .init = jlink_spi_init,
512 .devs.note = "SEGGER J-Link and compatible devices\n",
513 .map_flash_region = fallback_map,
514 .unmap_flash_region = fallback_unmap,
515 .delay = internal_delay,
516};