1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2019 Miklós Márton [email protected]
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 /*
19 * Driver for programming SPI flash chips using the SPI port
20 * of the STMicroelectronics's STLINK-V3 programmer/debugger.
21 *
22 * The implementation is inspired by the ST's STLINK-V3-BRIDGE C++ API:
23 * https://www.st.com/en/development-tools/stlink-v3-bridge.html
24 */
25
26 #include "flash.h"
27 #include "programmer.h"
28 #include "spi.h"
29
30 #include <libusb.h>
31 #include <limits.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 enum fw_version_check_result {
37 FW_VERSION_OK,
38 FW_VERSION_OLD,
39 };
40
41 enum spi_prescaler {
42 SPI_BAUDRATEPRESCALER_2 = 0,
43 SPI_BAUDRATEPRESCALER_4 = 1,
44 SPI_BAUDRATEPRESCALER_8 = 2,
45 SPI_BAUDRATEPRESCALER_16 = 3,
46 SPI_BAUDRATEPRESCALER_32 = 4,
47 SPI_BAUDRATEPRESCALER_64 = 5,
48 SPI_BAUDRATEPRESCALER_128 = 6,
49 SPI_BAUDRATEPRESCALER_256 = 7
50 };
51
52 enum spi_dir {
53 SPI_DIRECTION_2LINES_FULLDUPLEX = 0,
54 SPI_DIRECTION_2LINES_RXONLY = 1,
55 SPI_DIRECTION_1LINE_RX = 2,
56 SPI_DIRECTION_1LINE_TX = 3
57 };
58
59 enum spi_mode {
60 SPI_MODE_SLAVE = 0,
61 SPI_MODE_MASTER = 1
62 };
63
64 enum spi_datasize {
65 SPI_DATASIZE_16B = 0,
66 SPI_DATASIZE_8B = 1
67 };
68
69 enum spi_cpol {
70 SPI_CPOL_LOW = 0,
71 SPI_CPOL_HIGH = 1
72 };
73
74 enum spi_cpha {
75 SPI_CPHA_1EDGE = 0,
76 SPI_CPHA_2EDGE = 1
77 };
78
79 enum spi_firstbit {
80 SPI_FIRSTBIT_LSB = 0,
81 SPI_FIRSTBIT_MSB = 1
82 };
83
84 // ST calls the Chip select (CS) NSS == Negated Slave Select
85 enum spi_nss {
86 SPI_NSS_SOFT = 0,
87 SPI_NSS_HARD = 1
88 };
89
90 enum spi_nss_level {
91 SPI_NSS_LOW = 0,
92 SPI_NSS_HIGH = 1
93 };
94
95 #define ST_GETVERSION_EXT 0xFB
96
97 #define STLINK_BRIDGE_COMMAND 0xFC
98 #define STLINK_BRIDGE_CLOSE 0x01
99 #define STLINK_BRIDGE_GET_RWCMD_STATUS 0x02
100 #define STLINK_BRIDGE_GET_CLOCK 0x03
101 #define STLINK_BRIDGE_INIT_SPI 0x20
102 #define STLINK_BRIDGE_WRITE_SPI 0x21
103 #define STLINK_BRIDGE_READ_SPI 0x22
104 #define STLINK_BRIDGE_CS_SPI 0x23
105
106 #define STLINK_BRIDGE_SPI_ERROR 0x02
107
108 #define STLINK_SPI_COM 0x02
109
110 #define STLINK_EP_OUT 0x06
111 #define STLINK_EP_IN 0x86
112
113 #define FIRST_COMPATIBLE_BRIDGE_FW_VERSION 3
114
115 #define USB_TIMEOUT_IN_MS 5000
116
117 static const struct dev_entry devs_stlinkv3_spi[] = {
118 {0x0483, 0x374E, BAD, "STMicroelectronics", "STLINK-V3E"},
119 {0x0483, 0x374F, OK, "STMicroelectronics", "STLINK-V3S"},
120 {0x0483, 0x3753, OK, "STMicroelectronics", "STLINK-V3 dual VCP"},
121 {0x0483, 0x3754, NT, "STMicroelectronics", "STLINK-V3 no MSD"},
122 {0}
123 };
124
125 struct stlinkv3_spi_data {
126 struct libusb_context *usb_ctx;
127 libusb_device_handle *handle;
128 };
129
stlinkv3_command(uint8_t * command,size_t command_length,uint8_t * answer,size_t answer_length,const char * command_name,libusb_device_handle * stlinkv3_handle)130 static int stlinkv3_command(uint8_t *command, size_t command_length,
131 uint8_t *answer, size_t answer_length, const char *command_name,
132 libusb_device_handle *stlinkv3_handle)
133 {
134 int actual_length = 0;
135 int rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_OUT,
136 command, command_length,
137 &actual_length, USB_TIMEOUT_IN_MS);
138 if (rc != LIBUSB_TRANSFER_COMPLETED || (size_t)actual_length != command_length) {
139 msg_perr("Failed to issue the %s command: '%s'\n",
140 command_name,
141 libusb_error_name(rc));
142 return -1;
143 }
144
145 rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_IN,
146 answer, answer_length,
147 &actual_length, USB_TIMEOUT_IN_MS);
148 if (rc != LIBUSB_TRANSFER_COMPLETED || (size_t)actual_length != answer_length) {
149 msg_perr("Failed to get %s answer: '%s'\n",
150 command_name,
151 libusb_error_name(rc));
152 return -1;
153 }
154 return 0;
155 }
156
157 /**
158 * @param[out] bridge_input_clk Current input frequency in kHz of the given com.
159 */
stlinkv3_get_clk(uint32_t * bridge_input_clk,libusb_device_handle * stlinkv3_handle)160 static int stlinkv3_get_clk(uint32_t *bridge_input_clk, libusb_device_handle *stlinkv3_handle)
161 {
162 uint8_t command[16] = { 0 };
163 uint8_t answer[12];
164
165 if (bridge_input_clk == NULL)
166 return -1;
167
168 command[0] = STLINK_BRIDGE_COMMAND;
169 command[1] = STLINK_BRIDGE_GET_CLOCK;
170 command[2] = STLINK_SPI_COM;
171
172 if (stlinkv3_command(command, sizeof(command),
173 answer, sizeof(answer),
174 "STLINK_BRIDGE_GET_CLOCK",
175 stlinkv3_handle) != 0)
176 return -1;
177
178 *bridge_input_clk = (uint32_t)answer[4]
179 | (uint32_t)answer[5]<<8
180 | (uint32_t)answer[6]<<16
181 | (uint32_t)answer[7]<<24;
182 return 0;
183
184 }
185
stlinkv3_spi_calc_prescaler(uint16_t reqested_freq_in_kHz,enum spi_prescaler * prescaler,uint16_t * calculated_freq_in_kHz,libusb_device_handle * stlinkv3_handle)186 static int stlinkv3_spi_calc_prescaler(uint16_t reqested_freq_in_kHz,
187 enum spi_prescaler *prescaler,
188 uint16_t *calculated_freq_in_kHz,
189 libusb_device_handle *stlinkv3_handle)
190 {
191 uint32_t bridge_clk_in_kHz;
192 uint32_t calculated_prescaler = 1;
193 uint16_t prescaler_value;
194
195 if (stlinkv3_get_clk(&bridge_clk_in_kHz, stlinkv3_handle))
196 return -1;
197
198 calculated_prescaler = bridge_clk_in_kHz/reqested_freq_in_kHz;
199 // Apply a smaller frequency if not exact
200 if (calculated_prescaler <= 2) {
201 *prescaler = SPI_BAUDRATEPRESCALER_2;
202 prescaler_value = 2;
203 } else if (calculated_prescaler <= 4) {
204 *prescaler = SPI_BAUDRATEPRESCALER_4;
205 prescaler_value = 4;
206 } else if (calculated_prescaler <= 8) {
207 *prescaler = SPI_BAUDRATEPRESCALER_8;
208 prescaler_value = 8;
209 } else if (calculated_prescaler <= 16) {
210 *prescaler = SPI_BAUDRATEPRESCALER_16;
211 prescaler_value = 16;
212 } else if (calculated_prescaler <= 32) {
213 *prescaler = SPI_BAUDRATEPRESCALER_32;
214 prescaler_value = 32;
215 } else if (calculated_prescaler <= 64) {
216 *prescaler = SPI_BAUDRATEPRESCALER_64;
217 prescaler_value = 64;
218 } else if (calculated_prescaler <= 128) {
219 *prescaler = SPI_BAUDRATEPRESCALER_128;
220 prescaler_value = 128;
221 } else if (calculated_prescaler <= 256) {
222 *prescaler = SPI_BAUDRATEPRESCALER_256;
223 prescaler_value = 256;
224 } else {
225 // smaller frequency not possible
226 *prescaler = SPI_BAUDRATEPRESCALER_256;
227 prescaler_value = 256;
228 }
229
230 *calculated_freq_in_kHz = bridge_clk_in_kHz / prescaler_value;
231
232 return 0;
233 }
234
stlinkv3_check_version(enum fw_version_check_result * result,libusb_device_handle * stlinkv3_handle)235 static int stlinkv3_check_version(enum fw_version_check_result *result, libusb_device_handle *stlinkv3_handle)
236 {
237 uint8_t answer[12];
238 uint8_t command[16] = { 0 };
239
240 command[0] = ST_GETVERSION_EXT;
241 command[1] = 0x80;
242
243 if (stlinkv3_command(command, sizeof(command),
244 answer, sizeof(answer),
245 "ST_GETVERSION_EXT",
246 stlinkv3_handle) != 0)
247 return -1;
248
249 msg_pinfo("Connected to STLink V3 with bridge FW version: %d\n", answer[4]);
250 *result = answer[4] >= FIRST_COMPATIBLE_BRIDGE_FW_VERSION
251 ? FW_VERSION_OK
252 : FW_VERSION_OLD;
253 return 0;
254 }
255
stlinkv3_spi_open(uint16_t reqested_freq_in_kHz,libusb_device_handle * stlinkv3_handle)256 static int stlinkv3_spi_open(uint16_t reqested_freq_in_kHz, libusb_device_handle *stlinkv3_handle)
257 {
258 uint8_t command[16] = { 0 };
259 uint8_t answer[2];
260 uint16_t SCK_freq_in_kHz;
261 enum spi_prescaler prescaler;
262 enum fw_version_check_result fw_check_result;
263
264 if (stlinkv3_check_version(&fw_check_result, stlinkv3_handle)) {
265 msg_perr("Failed to query FW version\n");
266 return -1;
267 }
268
269 if (fw_check_result != FW_VERSION_OK) {
270 msg_pinfo("Your STLink V3 has a too old version of the bridge interface\n"
271 "Please update the firmware to version 2.33.25 or newer of the STSW-LINK007\n"
272 "which can be downloaded from here:\n"
273 "https://www.st.com/en/development-tools/stsw-link007.html\n");
274 return -1;
275 }
276
277 if (stlinkv3_spi_calc_prescaler(reqested_freq_in_kHz,
278 &prescaler,
279 &SCK_freq_in_kHz,
280 stlinkv3_handle)) {
281 msg_perr("Failed to calculate SPI clock prescaler\n");
282 return -1;
283 }
284 msg_pinfo("SCK frequency set to %d kHz\n", SCK_freq_in_kHz);
285
286 command[0] = STLINK_BRIDGE_COMMAND;
287 command[1] = STLINK_BRIDGE_INIT_SPI;
288 command[2] = SPI_DIRECTION_2LINES_FULLDUPLEX;
289 command[3] = (SPI_MODE_MASTER
290 | (SPI_CPHA_1EDGE << 1)
291 | (SPI_CPOL_LOW << 2)
292 | (SPI_FIRSTBIT_MSB << 3));
293 command[4] = SPI_DATASIZE_8B;
294 command[5] = SPI_NSS_SOFT;
295 command[6] = (uint8_t)prescaler;
296
297 return stlinkv3_command(command, sizeof(command),
298 answer, sizeof(answer),
299 "STLINK_BRIDGE_INIT_SPI",
300 stlinkv3_handle);
301 }
302
stlinkv3_get_last_readwrite_status(uint32_t * status,libusb_device_handle * stlinkv3_handle)303 static int stlinkv3_get_last_readwrite_status(uint32_t *status, libusb_device_handle *stlinkv3_handle)
304 {
305 uint8_t command[16] = { 0 };
306 uint16_t answer[4];
307
308 command[0] = STLINK_BRIDGE_COMMAND;
309 command[1] = STLINK_BRIDGE_GET_RWCMD_STATUS;
310
311 if (stlinkv3_command(command, sizeof(command),
312 (uint8_t *)answer, sizeof(answer),
313 "STLINK_BRIDGE_GET_RWCMD_STATUS",
314 stlinkv3_handle) != 0)
315 return -1;
316
317 *status = (uint32_t)answer[2] | (uint32_t)answer[3]<<16;
318 return 0;
319 }
320
stlinkv3_spi_set_SPI_NSS(enum spi_nss_level nss_level,libusb_device_handle * stlinkv3_handle)321 static int stlinkv3_spi_set_SPI_NSS(enum spi_nss_level nss_level, libusb_device_handle *stlinkv3_handle)
322 {
323 uint8_t command[16] = { 0 };
324 uint8_t answer[2];
325
326 command[0] = STLINK_BRIDGE_COMMAND;
327 command[1] = STLINK_BRIDGE_CS_SPI;
328 command[2] = (uint8_t) (nss_level);
329
330 if (stlinkv3_command(command, sizeof(command),
331 answer, sizeof(answer),
332 "STLINK_BRIDGE_CS_SPI",
333 stlinkv3_handle) != 0)
334 return -1;
335 return 0;
336 }
337
stlinkv3_spi_transmit(const struct flashctx * flash,unsigned int write_cnt,unsigned int read_cnt,const unsigned char * write_arr,unsigned char * read_arr)338 static int stlinkv3_spi_transmit(const struct flashctx *flash,
339 unsigned int write_cnt,
340 unsigned int read_cnt,
341 const unsigned char *write_arr,
342 unsigned char *read_arr)
343 {
344 struct stlinkv3_spi_data *stlinkv3_data = flash->mst->spi.data;
345 libusb_device_handle *stlinkv3_handle = stlinkv3_data->handle;
346 uint8_t command[16] = { 0 };
347 int rc = 0;
348 int actual_length = 0;
349 uint32_t rw_status = 0;
350 unsigned int i;
351
352 if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_LOW, stlinkv3_handle)) {
353 msg_perr("Failed to set the NSS pin to low\n");
354 return -1;
355 }
356
357 command[0] = STLINK_BRIDGE_COMMAND;
358 command[1] = STLINK_BRIDGE_WRITE_SPI;
359 command[2] = (uint8_t)write_cnt;
360 command[3] = (uint8_t)(write_cnt >> 8);
361
362 for (i = 0; (i < 8) && (i < write_cnt); i++)
363 command[4+i] = write_arr[i];
364
365 rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_OUT,
366 command, sizeof(command),
367 &actual_length, USB_TIMEOUT_IN_MS);
368 if (rc != LIBUSB_TRANSFER_COMPLETED || actual_length != sizeof(command)) {
369 msg_perr("Failed to issue the STLINK_BRIDGE_WRITE_SPI command: '%s'\n",
370 libusb_error_name(rc));
371 goto transmit_err;
372 }
373
374 if (write_cnt > 8) {
375 rc = libusb_bulk_transfer(stlinkv3_handle,
376 STLINK_EP_OUT,
377 (unsigned char *)&write_arr[8],
378 (unsigned int)(write_cnt - 8),
379 &actual_length,
380 USB_TIMEOUT_IN_MS);
381 if (rc != LIBUSB_TRANSFER_COMPLETED || (unsigned int)actual_length != (write_cnt - 8)) {
382 msg_perr("Failed to send the data after the STLINK_BRIDGE_WRITE_SPI command: '%s'\n",
383 libusb_error_name(rc));
384 goto transmit_err;
385 }
386 }
387
388 if (stlinkv3_get_last_readwrite_status(&rw_status, stlinkv3_handle))
389 return -1;
390
391 if (rw_status != 0) {
392 msg_perr("SPI read/write failure: %d\n", rw_status);
393 goto transmit_err;
394 }
395
396 if (read_cnt) {
397 command[1] = STLINK_BRIDGE_READ_SPI;
398 command[2] = (uint8_t)read_cnt;
399 command[3] = (uint8_t)(read_cnt >> 8);
400
401 rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_OUT,
402 command, sizeof(command),
403 &actual_length, USB_TIMEOUT_IN_MS);
404 if (rc != LIBUSB_TRANSFER_COMPLETED || (unsigned int)actual_length != sizeof(command)) {
405 msg_perr("Failed to issue the STLINK_BRIDGE_READ_SPI command: '%s'\n",
406 libusb_error_name(rc));
407 goto transmit_err;
408 }
409
410 rc = libusb_bulk_transfer(stlinkv3_handle,
411 STLINK_EP_IN,
412 (unsigned char *)read_arr,
413 (int)read_cnt,
414 &actual_length,
415 USB_TIMEOUT_IN_MS);
416 if (rc != LIBUSB_TRANSFER_COMPLETED || (unsigned int)actual_length != read_cnt) {
417 msg_perr("Failed to retrieve the STLINK_BRIDGE_READ_SPI answer: '%s'\n",
418 libusb_error_name(rc));
419 goto transmit_err;
420 }
421 }
422
423 if (stlinkv3_get_last_readwrite_status(&rw_status, stlinkv3_handle))
424 goto transmit_err;
425
426 if (rw_status != 0) {
427 msg_perr("SPI read/write failure: %d\n", rw_status);
428 goto transmit_err;
429 }
430
431 if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH, stlinkv3_handle)) {
432 msg_perr("Failed to set the NSS pin to high\n");
433 return -1;
434 }
435 return 0;
436
437 transmit_err:
438 if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH, stlinkv3_handle))
439 msg_perr("Failed to set the NSS pin to high\n");
440 return -1;
441 }
442
stlinkv3_spi_shutdown(void * data)443 static int stlinkv3_spi_shutdown(void *data)
444 {
445 struct stlinkv3_spi_data *stlinkv3_data = data;
446 uint8_t command[16] = { 0 };
447 uint8_t answer[2];
448
449 command[0] = STLINK_BRIDGE_COMMAND;
450 command[1] = STLINK_BRIDGE_CLOSE;
451 command[2] = STLINK_SPI_COM;
452
453 stlinkv3_command(command, sizeof(command),
454 answer, sizeof(answer),
455 "STLINK_BRIDGE_CLOSE",
456 stlinkv3_data->handle);
457
458 libusb_close(stlinkv3_data->handle);
459 libusb_exit(stlinkv3_data->usb_ctx);
460
461 free(data);
462 return 0;
463 }
464
465 static const struct spi_master spi_programmer_stlinkv3 = {
466 .max_data_read = UINT16_MAX,
467 .max_data_write = UINT16_MAX,
468 .command = stlinkv3_spi_transmit,
469 .read = default_spi_read,
470 .write_256 = default_spi_write_256,
471 .shutdown = stlinkv3_spi_shutdown,
472 };
473
stlinkv3_spi_init(const struct programmer_cfg * cfg)474 static int stlinkv3_spi_init(const struct programmer_cfg *cfg)
475 {
476 uint16_t sck_freq_kHz = 1000; // selecting 1 MHz SCK is a good bet
477 char *param_str;
478 char *endptr = NULL;
479 int ret = 1;
480 int devIndex = 0;
481 struct libusb_context *usb_ctx;
482 /* Initialize stlinkv3_handle to NULL for suppressing scan-build false positive core.uninitialized.Branch */
483 libusb_device_handle *stlinkv3_handle = NULL;
484 struct stlinkv3_spi_data *stlinkv3_data;
485
486 if (libusb_init(&usb_ctx)) {
487 msg_perr("Could not initialize libusb!\n");
488 return 1;
489 }
490
491 param_str = extract_programmer_param_str(cfg, "serial");
492 if (param_str)
493 msg_pdbg("Opening STLINK-V3 with serial: %s\n", param_str);
494
495
496 while (devs_stlinkv3_spi[devIndex].vendor_id != 0) {
497 stlinkv3_handle = usb_dev_get_by_vid_pid_serial(usb_ctx,
498 devs_stlinkv3_spi[devIndex].vendor_id,
499 devs_stlinkv3_spi[devIndex].device_id,
500 param_str);
501 if (stlinkv3_handle) {
502 if (devs_stlinkv3_spi[devIndex].status == BAD) {
503 msg_perr("The STLINK-V3 Mini/MiniE does not support the bridge interface\n");
504 free(param_str);
505 goto init_err_exit;
506 }
507 break;
508 }
509 devIndex++;
510 }
511
512 if (!stlinkv3_handle) {
513 if (param_str)
514 msg_perr("No STLINK-V3 seems to be connected with serial %s\n", param_str);
515 else
516 msg_perr("Could not find any connected STLINK-V3\n");
517 free(param_str);
518 goto init_err_exit;
519 }
520 free(param_str);
521
522 param_str = extract_programmer_param_str(cfg, "spispeed");
523 if (param_str) {
524 sck_freq_kHz = strtoul(param_str, &endptr, 0);
525 if (*endptr || sck_freq_kHz == 0) {
526 msg_perr("The spispeed parameter passed with invalid format: %s\n",
527 param_str);
528 msg_perr("Please pass the parameter "
529 "with a simple non-zero number in kHz\n");
530 free(param_str);
531 ret = -1;
532 goto init_err_exit;
533 }
534 free(param_str);
535 }
536
537 if (stlinkv3_spi_open(sck_freq_kHz, stlinkv3_handle))
538 goto init_err_exit;
539
540 stlinkv3_data = calloc(1, sizeof(*stlinkv3_data));
541 if (!stlinkv3_data) {
542 msg_perr("Unable to allocate space for SPI master data\n");
543 goto init_err_exit;
544 }
545
546 stlinkv3_data->usb_ctx = usb_ctx;
547 stlinkv3_data->handle = stlinkv3_handle;
548
549 return register_spi_master(&spi_programmer_stlinkv3, stlinkv3_data);
550
551 init_err_exit:
552 if (stlinkv3_handle)
553 libusb_close(stlinkv3_handle);
554 libusb_exit(usb_ctx);
555 return ret;
556 }
557
558 const struct programmer_entry programmer_stlinkv3_spi = {
559 .name = "stlinkv3_spi",
560 .type = USB,
561 .devs.dev = devs_stlinkv3_spi,
562 .init = stlinkv3_spi_init,
563 };
564