blob: 8b8533cab4e17262866e5ef7b3a08260a3c52df9 [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 Schinkab623c62020-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
Anastasia Klimchuk3c979982021-04-21 12:21:49 +100054struct jlink_spi_data {
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100055 struct jaylink_context *ctx;
56 struct jaylink_device_handle *devh;
Anastasia Klimchuk3c979982021-04-21 12:21:49 +100057 bool reset_cs;
58};
Marc Schink3578ec62016-03-17 16:23:03 +010059
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100060static bool assert_cs(struct jlink_spi_data *jlink_data)
Marc Schink3578ec62016-03-17 16:23:03 +010061{
62 int ret;
63
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100064 if (jlink_data->reset_cs) {
65 ret = jaylink_clear_reset(jlink_data->devh);
Marc Schink3578ec62016-03-17 16:23:03 +010066
67 if (ret != JAYLINK_OK) {
68 msg_perr("jaylink_clear_reset() failed: %s.\n", jaylink_strerror(ret));
69 return false;
70 }
71 } else {
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100072 ret = jaylink_jtag_clear_trst(jlink_data->devh);
Marc Schink3578ec62016-03-17 16:23:03 +010073
74 if (ret != JAYLINK_OK) {
75 msg_perr("jaylink_jtag_clear_trst() failed: %s.\n", jaylink_strerror(ret));
76 return false;
77 }
78 }
79
80 return true;
81}
82
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100083static bool deassert_cs(struct jlink_spi_data *jlink_data)
Marc Schink3578ec62016-03-17 16:23:03 +010084{
85 int ret;
86
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100087 if (jlink_data->reset_cs) {
88 ret = jaylink_set_reset(jlink_data->devh);
Marc Schink3578ec62016-03-17 16:23:03 +010089
90 if (ret != JAYLINK_OK) {
91 msg_perr("jaylink_set_reset() failed: %s.\n", jaylink_strerror(ret));
92 return false;
93 }
94 } else {
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +100095 ret = jaylink_jtag_set_trst(jlink_data->devh);
Marc Schink3578ec62016-03-17 16:23:03 +010096
97 if (ret != JAYLINK_OK) {
98 msg_perr("jaylink_jtag_set_trst() failed: %s.\n", jaylink_strerror(ret));
99 return false;
100 }
101 }
102
103 return true;
104}
105
Edward O'Callaghane4ddc362020-04-12 17:27:53 +1000106static int jlink_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
Marc Schink3578ec62016-03-17 16:23:03 +0100107 const unsigned char *writearr, unsigned char *readarr)
108{
109 uint32_t length;
110 uint8_t *buffer;
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000111 struct jlink_spi_data *jlink_data = flash->mst->spi.data;
Marc Schink3578ec62016-03-17 16:23:03 +0100112
113 length = writecnt + readcnt;
114
115 if (length > JTAG_MAX_TRANSFER_SIZE)
116 return SPI_INVALID_LENGTH;
117
118 buffer = malloc(length);
119
120 if (!buffer) {
121 msg_perr("Memory allocation failed.\n");
122 return SPI_GENERIC_ERROR;
123 }
124
125 /* Reverse all bytes because the device transfers data LSB first. */
126 reverse_bytes(buffer, writearr, writecnt);
127
128 memset(buffer + writecnt, 0x00, readcnt);
129
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000130 if (!assert_cs(jlink_data)) {
Marc Schink3578ec62016-03-17 16:23:03 +0100131 free(buffer);
132 return SPI_PROGRAMMER_ERROR;
133 }
134
135 int ret;
136
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000137 ret = jaylink_jtag_io(jlink_data->devh,
Anastasia Klimchuk3c979982021-04-21 12:21:49 +1000138 buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2);
Marc Schink3578ec62016-03-17 16:23:03 +0100139
140 if (ret != JAYLINK_OK) {
Angel Pons1ce155d2021-04-16 10:55:03 +0200141 msg_perr("jaylink_jtag_io() failed: %s.\n", jaylink_strerror(ret));
Marc Schink3578ec62016-03-17 16:23:03 +0100142 free(buffer);
143 return SPI_PROGRAMMER_ERROR;
144 }
145
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000146 if (!deassert_cs(jlink_data)) {
Marc Schink3578ec62016-03-17 16:23:03 +0100147 free(buffer);
148 return SPI_PROGRAMMER_ERROR;
149 }
150
151 /* Reverse all bytes because the device transfers data LSB first. */
152 reverse_bytes(readarr, buffer + writecnt, readcnt);
153 free(buffer);
154
155 return 0;
156}
157
Nico Huber90739d12021-05-11 17:53:34 +0200158static const struct spi_master spi_master_jlink_spi = {
Marc Schink3578ec62016-03-17 16:23:03 +0100159 /* Maximum data read size in one go (excluding opcode+address). */
160 .max_data_read = JTAG_MAX_TRANSFER_SIZE - 5,
161 /* Maximum data write size in one go (excluding opcode+address). */
162 .max_data_write = JTAG_MAX_TRANSFER_SIZE - 5,
163 .command = jlink_spi_send_command,
164 .multicommand = default_spi_send_multicommand,
165 .read = default_spi_read,
166 .write_256 = default_spi_write_256,
167 .write_aai = default_spi_write_aai,
168 .features = SPI_MASTER_4BA,
169};
170
171static int jlink_spi_shutdown(void *data)
172{
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000173 struct jlink_spi_data *jlink_data = data;
174 if (jlink_data->devh)
175 jaylink_close(jlink_data->devh);
Marc Schink3578ec62016-03-17 16:23:03 +0100176
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000177 jaylink_exit(jlink_data->ctx);
Marc Schink3578ec62016-03-17 16:23:03 +0100178
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000179 /* jlink_data->ctx, jlink_data->devh are freed by jaylink_close and jaylink_exit */
180 free(jlink_data);
Marc Schink3578ec62016-03-17 16:23:03 +0100181 return 0;
182}
183
Thomas Heijligen4f5169d2021-05-04 15:32:17 +0200184static int jlink_spi_init(void)
Marc Schink3578ec62016-03-17 16:23:03 +0100185{
186 char *arg;
187 unsigned long speed = 0;
Anastasia Klimchuk3c979982021-04-21 12:21:49 +1000188 struct jaylink_context *jaylink_ctx = NULL;
189 struct jaylink_device_handle *jaylink_devh = NULL;
190 bool reset_cs;
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000191 struct jlink_spi_data *jlink_data = NULL;
Marc Schink3578ec62016-03-17 16:23:03 +0100192
Marc Schink3578ec62016-03-17 16:23:03 +0100193 arg = extract_programmer_param("spispeed");
194
195 if (arg) {
196 char *endptr;
197
198 errno = 0;
199 speed = strtoul(arg, &endptr, 10);
200
201 if (*endptr != '\0' || errno != 0) {
202 msg_perr("Invalid SPI speed specified: %s.\n", arg);
203 free(arg);
204 return 1;
205 }
206
207 if (speed < 1) {
208 msg_perr("SPI speed must be at least 1 kHz.\n");
209 free(arg);
210 return 1;
211 }
212 }
213
214 free(arg);
215
216 int ret;
217 bool use_serial_number;
218 uint32_t serial_number;
219
220 arg = extract_programmer_param("serial");
221
222 if (arg) {
223 if (!strlen(arg)) {
Angel Pons1ce155d2021-04-16 10:55:03 +0200224 msg_perr("Empty serial number specified.\n");
Marc Schink3578ec62016-03-17 16:23:03 +0100225 free(arg);
226 return 1;
227 }
228
229 ret = jaylink_parse_serial_number(arg, &serial_number);
230
231 if (ret == JAYLINK_ERR) {
232 msg_perr("Invalid serial number specified: %s.\n", arg);
233 free(arg);
234 return 1;
235 } if (ret != JAYLINK_OK) {
236 msg_perr("jaylink_parse_serial_number() failed: %s.\n", jaylink_strerror(ret));
237 free(arg);
238 return 1;
239 }
240
241 use_serial_number = true;
242 } else {
243 use_serial_number = false;
244 }
245
246 free(arg);
247
248 reset_cs = true;
249 arg = extract_programmer_param("cs");
250
251 if (arg) {
252 if (!strcasecmp(arg, "reset")) {
253 reset_cs = true;
254 } else if (!strcasecmp(arg, "trst")) {
255 reset_cs = false;
256 } else {
257 msg_perr("Invalid chip select pin specified: '%s'.\n", arg);
258 free(arg);
259 return 1;
260 }
261 }
262
263 free(arg);
264
265 if (reset_cs)
266 msg_pdbg("Using RESET as chip select signal.\n");
267 else
268 msg_pdbg("Using TRST as chip select signal.\n");
269
270 ret = jaylink_init(&jaylink_ctx);
271
272 if (ret != JAYLINK_OK) {
273 msg_perr("jaylink_init() failed: %s.\n", jaylink_strerror(ret));
274 return 1;
275 }
276
277 ret = jaylink_discovery_scan(jaylink_ctx, 0);
278
279 if (ret != JAYLINK_OK) {
Angel Pons1ce155d2021-04-16 10:55:03 +0200280 msg_perr("jaylink_discovery_scan() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000281 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100282 }
283
284 struct jaylink_device **devs;
285
286 ret = jaylink_get_devices(jaylink_ctx, &devs, NULL);
287
288 if (ret != JAYLINK_OK) {
289 msg_perr("jaylink_get_devices() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000290 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100291 }
292
293 if (!use_serial_number)
294 msg_pdbg("No device selected, using first device.\n");
295
296 size_t i;
297 struct jaylink_device *dev;
298 bool device_found = false;
299
300 for (i = 0; devs[i]; i++) {
301 if (use_serial_number) {
302 uint32_t tmp;
303
304 ret = jaylink_device_get_serial_number(devs[i], &tmp);
305
306 if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
307 continue;
308 } else if (ret != JAYLINK_OK) {
309 msg_pwarn("jaylink_device_get_serial_number() failed: %s.\n",
310 jaylink_strerror(ret));
311 continue;
312 }
313
314 if (serial_number != tmp)
315 continue;
316 }
317
318 ret = jaylink_open(devs[i], &jaylink_devh);
319
320 if (ret == JAYLINK_OK) {
321 dev = devs[i];
322 device_found = true;
323 break;
324 }
325
326 jaylink_devh = NULL;
327 }
328
329 jaylink_free_devices(devs, true);
330
331 if (!device_found) {
332 msg_perr("No J-Link device found.\n");
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000333 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100334 }
335
336 size_t length;
337 char *firmware_version;
338
339 ret = jaylink_get_firmware_version(jaylink_devh, &firmware_version,
340 &length);
341
342 if (ret != JAYLINK_OK) {
343 msg_perr("jaylink_get_firmware_version() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000344 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100345 } else if (length > 0) {
346 msg_pdbg("Firmware: %s\n", firmware_version);
347 free(firmware_version);
348 }
349
350 ret = jaylink_device_get_serial_number(dev, &serial_number);
351
352 if (ret == JAYLINK_OK) {
353 msg_pdbg("S/N: %" PRIu32 "\n", serial_number);
354 } else if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
355 msg_pdbg("S/N: N/A\n");
356 } else {
357 msg_perr("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000358 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100359 }
360
Angel Ponsf41d2482021-06-07 13:29:13 +0200361 uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE] = { 0 };
Marc Schink3578ec62016-03-17 16:23:03 +0100362
Marc Schink3578ec62016-03-17 16:23:03 +0100363 ret = jaylink_get_caps(jaylink_devh, caps);
364
365 if (ret != JAYLINK_OK) {
366 msg_perr("jaylink_get_caps() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000367 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100368 }
369
370 if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
371 ret = jaylink_get_extended_caps(jaylink_devh, caps);
372
373 if (ret != JAYLINK_OK) {
Angel Pons1ce155d2021-04-16 10:55:03 +0200374 msg_perr("jaylink_get_extended_caps() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000375 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100376 }
377 }
378
379 uint32_t ifaces;
380
381 ret = jaylink_get_available_interfaces(jaylink_devh, &ifaces);
382
383 if (ret != JAYLINK_OK) {
384 msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000385 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100386 }
387
388 if (!(ifaces & (1 << JAYLINK_TIF_JTAG))) {
389 msg_perr("Device does not support JTAG interface.\n");
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000390 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100391 }
392
393 ret = jaylink_select_interface(jaylink_devh, JAYLINK_TIF_JTAG, NULL);
394
395 if (ret != JAYLINK_OK) {
396 msg_perr("jaylink_select_interface() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000397 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100398 }
399
400 struct jaylink_hardware_status hwstat;
401
402 ret = jaylink_get_hardware_status(jaylink_devh, &hwstat);
403
404 if (ret != JAYLINK_OK) {
405 msg_perr("jaylink_get_hardware_status() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000406 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100407 }
408
409 msg_pdbg("VTarget: %u.%03u V\n", hwstat.target_voltage / 1000,
410 hwstat.target_voltage % 1000);
411
412 if (hwstat.target_voltage < MIN_TARGET_VOLTAGE) {
413 msg_perr("Target voltage is below %u.%03u V. You need to attach VTref to the I/O voltage of "
414 "the chip.\n", MIN_TARGET_VOLTAGE / 1000, MIN_TARGET_VOLTAGE % 1000);
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000415 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100416 }
417
418 struct jaylink_speed device_speeds;
419
420 device_speeds.freq = DEFAULT_FREQ;
421 device_speeds.div = DEFAULT_FREQ_DIV;
422
423 if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
424 ret = jaylink_get_speeds(jaylink_devh, &device_speeds);
425
426 if (ret != JAYLINK_OK) {
427 msg_perr("jaylink_get_speeds() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000428 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100429 }
430 }
431
432 device_speeds.freq /= 1000;
433
434 msg_pdbg("Maximum SPI speed: %" PRIu32 " kHz\n", device_speeds.freq / device_speeds.div);
435
436 if (!speed) {
437 speed = device_speeds.freq / device_speeds.div;
438 msg_pdbg("SPI speed not specified, using %lu kHz.\n", speed);
439 }
440
441 if (speed > (device_speeds.freq / device_speeds.div)) {
442 msg_perr("Specified SPI speed of %lu kHz is too high. Maximum is %" PRIu32 " kHz.\n", speed,
443 device_speeds.freq / device_speeds.div);
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000444 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100445 }
446
447 ret = jaylink_set_speed(jaylink_devh, speed);
448
449 if (ret != JAYLINK_OK) {
450 msg_perr("jaylink_set_speed() failed: %s.\n", jaylink_strerror(ret));
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000451 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100452 }
453
454 msg_pdbg("SPI speed: %lu kHz\n", speed);
455
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000456 jlink_data = calloc(1, sizeof(*jlink_data));
457 if (!jlink_data) {
Anastasia Klimchuk3c979982021-04-21 12:21:49 +1000458 msg_perr("Unable to allocate space for SPI master data\n");
459 goto init_err;
460 }
461
462 /* jaylink_ctx, jaylink_devh are allocated by jaylink_init and jaylink_open */
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000463 jlink_data->ctx = jaylink_ctx;
464 jlink_data->devh = jaylink_devh;
465 jlink_data->reset_cs = reset_cs;
Anastasia Klimchuk3c979982021-04-21 12:21:49 +1000466
Marc Schink3578ec62016-03-17 16:23:03 +0100467 /* Ensure that the CS signal is not active initially. */
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000468 if (!deassert_cs(jlink_data))
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000469 goto init_err;
Marc Schink3578ec62016-03-17 16:23:03 +0100470
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000471 if (register_shutdown(jlink_spi_shutdown, jlink_data))
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000472 goto init_err;
Nico Huber90739d12021-05-11 17:53:34 +0200473 register_spi_master(&spi_master_jlink_spi, jlink_data);
Marc Schink3578ec62016-03-17 16:23:03 +0100474
475 return 0;
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000476
477init_err:
478 if (jaylink_devh)
479 jaylink_close(jaylink_devh);
480
481 jaylink_exit(jaylink_ctx);
482
Anastasia Klimchuk3c979982021-04-21 12:21:49 +1000483 /* jaylink_ctx, jaylink_devh are freed by jaylink_close and jaylink_exit */
Anastasia Klimchuk62fb7642021-04-26 10:58:16 +1000484 if (jlink_data)
485 free(jlink_data);
Anastasia Klimchuk3c979982021-04-21 12:21:49 +1000486
Anastasia Klimchuk267ca962021-04-14 09:52:36 +1000487 return 1;
Marc Schink3578ec62016-03-17 16:23:03 +0100488}
Thomas Heijligen4f5169d2021-05-04 15:32:17 +0200489
490const struct programmer_entry programmer_jlink_spi = {
491 .name = "jlink_spi",
492 .type = OTHER,
493 .init = jlink_spi_init,
494 .devs.note = "SEGGER J-Link and compatible devices\n",
495 .map_flash_region = fallback_map,
496 .unmap_flash_region = fallback_unmap,
497 .delay = internal_delay,
498};