blob: 51c9263713e2ec8685c6644a5f67e33d29282d85 [file] [log] [blame]
hailfingerdfb32a02010-01-19 11:15:48 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2010 Carl-Daniel Hailfinger
David Hendricksfe05e742015-08-15 17:29:39 -07005 * Copyright (C) 2015 Simon Glass
6 * Copyright (C) 2015 Stefan Tauner
hailfingerdfb32a02010-01-19 11:15:48 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
hailfingerdfb32a02010-01-19 11:15:48 +000016 */
17
Patrick Georgibd31cdd2017-02-03 19:16:12 +010018#include "platform.h"
David Hendricksfe05e742015-08-15 17:29:39 -070019
20#include <stdlib.h>
hailfinger7a009082010-11-09 23:30:43 +000021#include <stdio.h>
hailfingerdfb32a02010-01-19 11:15:48 +000022#include <string.h>
David Hendricksfe05e742015-08-15 17:29:39 -070023#include <limits.h>
24#include <errno.h>
25
26#if IS_WINDOWS
27#include <lusb0_usb.h>
28#else
David Hendricksf9ecb452015-11-04 15:40:27 -080029#include <libusb.h>
David Hendricksfe05e742015-08-15 17:29:39 -070030#endif
31
hailfingerdfb32a02010-01-19 11:15:48 +000032#include "flash.h"
David Hendrickscd20ea42015-11-17 22:33:35 -080033#include "flashchips.h"
snelson8913d082010-02-26 05:48:29 +000034#include "chipdrivers.h"
hailfinger428f6852010-07-27 22:41:39 +000035#include "programmer.h"
hailfingerdfb32a02010-01-19 11:15:48 +000036#include "spi.h"
37
stepan4c06de72011-01-28 09:00:15 +000038#define FIRMWARE_VERSION(x,y,z) ((x << 16) | (y << 8) | z)
hailfingerdfb32a02010-01-19 11:15:48 +000039#define DEFAULT_TIMEOUT 3000
David Hendricksf9ecb452015-11-04 15:40:27 -080040#define DEDIPROG_ASYNC_TRANSFERS 8 /* at most 8 asynchronous transfers */
41#define REQTYPE_OTHER_OUT (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0x43 */
42#define REQTYPE_OTHER_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0xC3 */
43#define REQTYPE_EP_OUT (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0x42 */
44#define REQTYPE_EP_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0xC2 */
45struct libusb_context *usb_ctx;
46static libusb_device_handle *dediprog_handle;
David Hendricksd7468582015-11-12 15:21:12 -080047static int dediprog_in_endpoint;
48static int dediprog_out_endpoint;
David Hendricksf9ecb452015-11-04 15:40:27 -080049static int dediprog_firmwareversion = FIRMWARE_VERSION(0, 0, 0);
hailfingerdfb32a02010-01-19 11:15:48 +000050
David Hendricks6702e072015-08-15 18:09:04 -070051enum dediprog_devtype {
52 DEV_UNKNOWN = 0,
53 DEV_SF100 = 100,
54 DEV_SF600 = 600,
55};
56
57enum dediprog_devtype dediprog_devicetype;
58
David Hendricksfe05e742015-08-15 17:29:39 -070059enum dediprog_leds {
60 LED_INVALID = -1,
61 LED_NONE = 0,
Simon Glasse53cc1d2015-01-08 05:48:51 -070062 LED_PASS = 1 << 0,
63 LED_BUSY = 1 << 1,
64 LED_ERROR = 1 << 2,
65 LED_ALL = 7,
66};
67
Simon Glassa1f80682015-01-08 05:55:29 -070068/* IO bits for CMD_SET_IO_LED message */
David Hendricksfe05e742015-08-15 17:29:39 -070069enum dediprog_ios {
Simon Glassa1f80682015-01-08 05:55:29 -070070 IO1 = 1 << 0,
71 IO2 = 1 << 1,
72 IO3 = 1 << 2,
73 IO4 = 1 << 3,
74};
75
David Hendricksfe05e742015-08-15 17:29:39 -070076enum dediprog_cmds {
77 CMD_TRANSCEIVE = 0x01,
78 CMD_POLL_STATUS_REG = 0x02,
79 CMD_SET_VPP = 0x03,
80 CMD_SET_TARGET = 0x04,
81 CMD_READ_EEPROM = 0x05,
82 CMD_WRITE_EEPROM = 0x06,
83 CMD_SET_IO_LED = 0x07,
84 CMD_READ_PROG_INFO = 0x08,
85 CMD_SET_VCC = 0x09,
86 CMD_SET_STANDALONE = 0x0A,
David Hendricks28fbdfb2015-08-15 18:04:37 -070087 CMD_SET_VOLTAGE = 0x0B, /* Only in firmware older than 6.0.0 */
David Hendricksfe05e742015-08-15 17:29:39 -070088 CMD_GET_BUTTON = 0x11,
89 CMD_GET_UID = 0x12,
90 CMD_SET_CS = 0x14,
91 CMD_IO_MODE = 0x15,
92 CMD_FW_UPDATE = 0x1A,
93 CMD_FPGA_UPDATE = 0x1B,
94 CMD_READ_FPGA_VERSION = 0x1C,
95 CMD_SET_HOLD = 0x1D,
96 CMD_READ = 0x20,
97 CMD_WRITE = 0x30,
98 CMD_WRITE_AT45DB = 0x31,
99 CMD_NAND_WRITE = 0x32,
100 CMD_NAND_READ = 0x33,
101 CMD_SET_SPI_CLK = 0x61,
102 CMD_CHECK_SOCKET = 0x62,
103 CMD_DOWNLOAD_PRJ = 0x63,
104 CMD_READ_PRJ_NAME = 0x64,
105 // New protocol/firmware only
106 CMD_CHECK_SDCARD = 0x65,
107 CMD_READ_PRJ = 0x66,
Simon Glassa1f80682015-01-08 05:55:29 -0700108};
109
David Hendricksfe05e742015-08-15 17:29:39 -0700110enum dediprog_target {
111 FLASH_TYPE_APPLICATION_FLASH_1 = 0,
112 FLASH_TYPE_FLASH_CARD,
113 FLASH_TYPE_APPLICATION_FLASH_2,
114 FLASH_TYPE_SOCKET,
Simon Glassa1f80682015-01-08 05:55:29 -0700115};
116
David Hendricksfe05e742015-08-15 17:29:39 -0700117enum dediprog_readmode {
118 READ_MODE_STD = 1,
119 READ_MODE_FAST = 2,
120 READ_MODE_ATMEL45 = 3,
121 READ_MODE_4B_ADDR_FAST = 4,
122 READ_MODE_4B_ADDR_FAST_0x0C = 5, /* New protocol only */
Simon Glassd01002b2015-01-08 05:44:16 -0700123};
124
David Hendricksfe05e742015-08-15 17:29:39 -0700125enum dediprog_writemode {
126 WRITE_MODE_PAGE_PGM = 1,
127 WRITE_MODE_PAGE_WRITE = 2,
128 WRITE_MODE_1B_AAI = 3,
129 WRITE_MODE_2B_AAI = 4,
130 WRITE_MODE_128B_PAGE = 5,
131 WRITE_MODE_PAGE_AT26DF041 = 6,
132 WRITE_MODE_SILICON_BLUE_FPGA = 7,
133 WRITE_MODE_64B_PAGE_NUMONYX_PCM = 8, /* unit of length 512 bytes */
134 WRITE_MODE_4B_ADDR_256B_PAGE_PGM = 9,
135 WRITE_MODE_32B_PAGE_PGM_MXIC_512K = 10, /* unit of length 512 bytes */
136 WRITE_MODE_4B_ADDR_256B_PAGE_PGM_0x12 = 11,
137 WRITE_MODE_4B_ADDR_256B_PAGE_PGM_FLAGS = 12,
Simon Glassd01002b2015-01-08 05:44:16 -0700138};
139
David Hendrickscf453d82015-11-16 20:19:57 -0800140enum dediprog_standalone_mode {
141 ENTER_STANDALONE_MODE = 0,
142 LEAVE_STANDALONE_MODE = 1,
143};
144
Edward O'Callaghana88395f2019-02-27 18:44:04 +1100145const struct dev_entry devs_dediprog[] = {
146 {0x0483, 0xDADA, OK, "Dediprog", "SF100/SF200/SF600"},
147
148 {0},
149};
150
David Hendricksf9ecb452015-11-04 15:40:27 -0800151#ifndef LIBUSB_HAVE_ERROR_NAME
152/* Quick and dirty replacement for missing libusb_error_name in older libusb 1.0. */
153const char *libusb_error_name(int error_code)
154{
155 /* 18 chars for text, rest for number, sign, nullbyte. */
156 static char my_libusb_error[18 + 6];
David Hendricksfe05e742015-08-15 17:29:39 -0700157
David Hendricksf9ecb452015-11-04 15:40:27 -0800158 sprintf(my_libusb_error, "libusb error code %i", error_code);
159 return my_libusb_error;
160}
161#endif
David Hendricksfe05e742015-08-15 17:29:39 -0700162
David Hendricks14e82e52015-08-15 17:59:03 -0700163/* Returns true if firmware (and thus hardware) supports the "new" protocol */
164static int is_new_prot(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000165{
David Hendricks6702e072015-08-15 18:09:04 -0700166 switch (dediprog_devicetype) {
167 case DEV_SF100:
168 return dediprog_firmwareversion >= FIRMWARE_VERSION(5, 5, 0);
169 case DEV_SF600:
170 return dediprog_firmwareversion >= FIRMWARE_VERSION(6, 9, 0);
171 default:
172 return 0;
173 }
hailfingerdfb32a02010-01-19 11:15:48 +0000174}
David Hendricks14e82e52015-08-15 17:59:03 -0700175
David Hendricksf9ecb452015-11-04 15:40:27 -0800176struct dediprog_transfer_status {
177 int error; /* OK if 0, ERROR else */
178 unsigned int queued_idx;
179 unsigned int finished_idx;
180};
181
182static void dediprog_bulk_read_cb(struct libusb_transfer *const transfer)
183{
184 struct dediprog_transfer_status *const status = (struct dediprog_transfer_status *)transfer->user_data;
185 if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
186 status->error = 1;
187 msg_perr("SPI bulk read failed!\n");
188 }
189 ++status->finished_idx;
190}
191
192static int dediprog_bulk_read_poll(const struct dediprog_transfer_status *const status, const int finish)
193{
194 if (status->finished_idx >= status->queued_idx)
195 return 0;
196
197 do {
198 struct timeval timeout = { 10, 0 };
199 const int ret = libusb_handle_events_timeout_completed(usb_ctx, &timeout, NULL);
200 if (ret < 0) {
201 msg_perr("Polling read events failed: %i %s!\n", ret, libusb_error_name(ret));
202 return 1;
203 }
204 } while (finish && (status->finished_idx < status->queued_idx));
205 return 0;
206}
207
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100208static int dediprog_read(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, uint8_t *bytes, size_t size)
David Hendricks14e82e52015-08-15 17:59:03 -0700209{
David Hendricksf9ecb452015-11-04 15:40:27 -0800210 return libusb_control_transfer(dediprog_handle, REQTYPE_EP_IN, cmd, value, idx,
211 (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
David Hendricks14e82e52015-08-15 17:59:03 -0700212}
213
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100214static int dediprog_write(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size)
David Hendricks14e82e52015-08-15 17:59:03 -0700215{
David Hendricksf9ecb452015-11-04 15:40:27 -0800216 return libusb_control_transfer(dediprog_handle, REQTYPE_EP_OUT, cmd, value, idx,
217 (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
David Hendricks14e82e52015-08-15 17:59:03 -0700218}
hailfingerdfb32a02010-01-19 11:15:48 +0000219
David Hendricksa7f99ac2015-11-12 16:42:03 -0800220static int dediprog_read_other(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size)
221{
222 return libusb_control_transfer(dediprog_handle, REQTYPE_OTHER_IN, cmd, value, idx,
223 (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
224}
David Hendricksf9ecb452015-11-04 15:40:27 -0800225
David Hendricksfe05e742015-08-15 17:29:39 -0700226/* This function sets the GPIOs connected to the LEDs as well as IO1-IO4. */
stepan4c06de72011-01-28 09:00:15 +0000227static int dediprog_set_leds(int leds)
228{
David Hendricksfe05e742015-08-15 17:29:39 -0700229 if (leds < LED_NONE || leds > LED_ALL)
Simon Glasse53cc1d2015-01-08 05:48:51 -0700230 leds = LED_ALL;
stepan4c06de72011-01-28 09:00:15 +0000231
David Hendricks14e82e52015-08-15 17:59:03 -0700232 /* Older Dediprogs with 2.x.x and 3.x.x firmware only had two LEDs, assigned to different bits. So map
233 * them around if we have an old device. On those devices the LEDs map as follows:
stepan4c06de72011-01-28 09:00:15 +0000234 * bit 2 == 0: green light is on.
David Hendricks14e82e52015-08-15 17:59:03 -0700235 * bit 0 == 0: red light is on.
236 *
237 * Additionally, the command structure has changed with the "new" protocol.
238 *
239 * FIXME: take IO pins into account
stepan4c06de72011-01-28 09:00:15 +0000240 */
David Hendricks14e82e52015-08-15 17:59:03 -0700241 int target_leds, ret;
242 if (is_new_prot()) {
243 target_leds = (leds ^ 7) << 8;
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100244 ret = dediprog_write(CMD_SET_IO_LED, target_leds, 0, NULL, 0);
stepan4c06de72011-01-28 09:00:15 +0000245 } else {
David Hendricks14e82e52015-08-15 17:59:03 -0700246 if (dediprog_firmwareversion < FIRMWARE_VERSION(5, 0, 0)) {
247 target_leds = ((leds & LED_ERROR) >> 2) | ((leds & LED_PASS) << 2);
248 } else {
249 target_leds = leds;
250 }
251 target_leds ^= 7;
252
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100253 ret = dediprog_write(CMD_SET_IO_LED, 0x9, target_leds, NULL, 0);
Simon Glass543101a2015-01-08 06:28:13 -0700254 }
David Hendricksfe05e742015-08-15 17:29:39 -0700255
stepan4c06de72011-01-28 09:00:15 +0000256 if (ret != 0x0) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800257 msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, libusb_error_name(ret));
stepan4c06de72011-01-28 09:00:15 +0000258 return 1;
259 }
260
stepan4c06de72011-01-28 09:00:15 +0000261 return 0;
262}
263
David Hendricksfe05e742015-08-15 17:29:39 -0700264struct dediprog_spispeeds {
265 const char *const name;
266 const int speed;
267};
268
269static const struct dediprog_spispeeds spispeeds[] = {
270 { "24M", 0x0 },
271 { "12M", 0x2 },
272 { "8M", 0x1 },
273 { "3M", 0x3 },
274 { "2.18M", 0x4 },
275 { "1.5M", 0x5 },
276 { "750k", 0x6 },
277 { "375k", 0x7 },
278 { NULL, 0x0 },
279};
280
281static int dediprog_set_spi_speed(unsigned int spispeed_idx)
hailfingerdfb32a02010-01-19 11:15:48 +0000282{
David Hendricksfe05e742015-08-15 17:29:39 -0700283 if (dediprog_firmwareversion < FIRMWARE_VERSION(5, 0, 0)) {
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100284 msg_pwarn("Skipping to set SPI speed because firmware is too old.\n");
David Hendricksfe05e742015-08-15 17:29:39 -0700285 return 0;
286 }
hailfingerdfb32a02010-01-19 11:15:48 +0000287
David Hendricksfe05e742015-08-15 17:29:39 -0700288 const struct dediprog_spispeeds *spispeed = &spispeeds[spispeed_idx];
289 msg_pdbg("SPI speed is %sHz\n", spispeed->name);
hailfingerdfb32a02010-01-19 11:15:48 +0000290
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100291 int ret = dediprog_write(CMD_SET_SPI_CLK, spispeed->speed, 0, NULL, 0);
hailfingerdfb32a02010-01-19 11:15:48 +0000292 if (ret != 0x0) {
David Hendricksfe05e742015-08-15 17:29:39 -0700293 msg_perr("Command Set SPI Speed 0x%x failed!\n", spispeed->speed);
hailfingerdfb32a02010-01-19 11:15:48 +0000294 return 1;
295 }
296 return 0;
297}
298
hailfingerfb6287d2010-11-16 21:25:29 +0000299/* Bulk read interface, will read multiple 512 byte chunks aligned to 512 bytes.
300 * @start start address
301 * @len length
302 * @return 0 on success, 1 on failure
303 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700304static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf,
stefanctc5eb8a92011-11-23 09:13:48 +0000305 unsigned int start, unsigned int len)
hailfingerfb6287d2010-11-16 21:25:29 +0000306{
David Hendricksf9ecb452015-11-04 15:40:27 -0800307 int ret, err = 1;
stefanctc5eb8a92011-11-23 09:13:48 +0000308 unsigned int i;
hailfingerfb6287d2010-11-16 21:25:29 +0000309 /* chunksize must be 512, other sizes will NOT work at all. */
stefanctc5eb8a92011-11-23 09:13:48 +0000310 const unsigned int chunksize = 0x200;
311 const unsigned int count = len / chunksize;
David Hendricks14e82e52015-08-15 17:59:03 -0700312 unsigned int cmd_len;
David Hendricksf9ecb452015-11-04 15:40:27 -0800313 struct dediprog_transfer_status status = { 0, 0, 0 };
314 struct libusb_transfer *transfers[DEDIPROG_ASYNC_TRANSFERS] = { NULL, };
315 struct libusb_transfer *transfer;
hailfingerfb6287d2010-11-16 21:25:29 +0000316
317 if ((start % chunksize) || (len % chunksize)) {
318 msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
319 "at flashrom@flashrom.org\n", __func__, start, len);
320 return 1;
321 }
322
323 /* No idea if the hardware can handle empty reads, so chicken out. */
324 if (!len)
325 return 0;
David Hendricks14e82e52015-08-15 17:59:03 -0700326 /* Command Read SPI Bulk. */
327 if (is_new_prot()) {
328 const uint8_t read_cmd[] = {
329 count & 0xff,
330 (count >> 8) & 0xff,
331 0,
332 READ_MODE_FAST,
333 0,
334 0,
335 start & 0xff,
336 (start >> 8) & 0xff,
337 (start >> 16) & 0xff,
338 (start >> 24) & 0xff,
339 };
340
341 cmd_len = sizeof(read_cmd);
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100342 ret = dediprog_write(CMD_READ, 0, 0, read_cmd, cmd_len);
David Hendricks14e82e52015-08-15 17:59:03 -0700343 } else {
344 const uint8_t read_cmd[] = {count & 0xff,
345 (count >> 8) & 0xff,
346 chunksize & 0xff,
347 (chunksize >> 8) & 0xff};
348
349 cmd_len = sizeof(read_cmd);
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100350 ret = dediprog_write(CMD_READ, start % 0x10000, start / 0x10000, read_cmd, cmd_len);
David Hendricks14e82e52015-08-15 17:59:03 -0700351 }
352 if (ret != cmd_len) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800353 msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, libusb_error_name(ret));
hailfingerfb6287d2010-11-16 21:25:29 +0000354 return 1;
355 }
356
David Hendricksf9ecb452015-11-04 15:40:27 -0800357 /*
358 * Ring buffer of bulk transfers.
359 * Poll until at least one transfer is ready,
360 * schedule next transfers until buffer is full.
361 */
hailfingerfb6287d2010-11-16 21:25:29 +0000362
David Hendricksf9ecb452015-11-04 15:40:27 -0800363 /* Allocate bulk transfers. */
364 for (i = 0; i < min(DEDIPROG_ASYNC_TRANSFERS, count); ++i) {
365 transfers[i] = libusb_alloc_transfer(0);
366 if (!transfers[i]) {
367 msg_perr("Allocating libusb transfer %i failed: %s!\n", i, libusb_error_name(ret));
368 goto _err_free;
369 }
370 }
371
372 /* Now transfer requested chunks using libusb's asynchronous interface. */
373 while (!status.error && (status.queued_idx < count)) {
374 while ((status.queued_idx - status.finished_idx) < DEDIPROG_ASYNC_TRANSFERS) {
375 transfer = transfers[status.queued_idx % DEDIPROG_ASYNC_TRANSFERS];
376 libusb_fill_bulk_transfer(transfer, dediprog_handle, 0x80 | dediprog_in_endpoint,
377 (unsigned char *)buf + status.queued_idx * chunksize, chunksize,
378 dediprog_bulk_read_cb, &status, DEFAULT_TIMEOUT);
379 transfer->flags |= LIBUSB_TRANSFER_SHORT_NOT_OK;
380 ret = libusb_submit_transfer(transfer);
381 if (ret < 0) {
382 msg_perr("Submitting SPI bulk read %i failed: %i %s!\n",
383 status.queued_idx, ret, libusb_error_name(ret));
384 goto _err_free;
385 }
386 ++status.queued_idx;
387 }
388 if (dediprog_bulk_read_poll(&status, 0))
389 goto _err_free;
390 }
391 /* Wait for transfers to finish. */
392 if (dediprog_bulk_read_poll(&status, 1))
393 goto _err_free;
394 /* Check if everything has been transmitted. */
395 if ((status.finished_idx < count) || status.error)
396 goto _err_free;
397
398 err = 0;
399
400_err_free:
401 dediprog_bulk_read_poll(&status, 1);
402 for (i = 0; i < DEDIPROG_ASYNC_TRANSFERS; ++i)
403 if (transfers[i]) libusb_free_transfer(transfers[i]);
404 return err;
hailfingerfb6287d2010-11-16 21:25:29 +0000405}
406
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700407static int dediprog_spi_read(struct flashctx *flash, uint8_t *buf,
stefanctc5eb8a92011-11-23 09:13:48 +0000408 unsigned int start, unsigned int len)
hailfingerdfb32a02010-01-19 11:15:48 +0000409{
hailfingerfb6287d2010-11-16 21:25:29 +0000410 int ret;
411 /* chunksize must be 512, other sizes will NOT work at all. */
stefanctc5eb8a92011-11-23 09:13:48 +0000412 const unsigned int chunksize = 0x200;
413 unsigned int residue = start % chunksize ? chunksize - start % chunksize : 0;
414 unsigned int bulklen;
hailfingerfb6287d2010-11-16 21:25:29 +0000415
Simon Glasse53cc1d2015-01-08 05:48:51 -0700416 dediprog_set_leds(LED_BUSY);
stepan4c06de72011-01-28 09:00:15 +0000417
hailfingerfb6287d2010-11-16 21:25:29 +0000418 if (residue) {
419 msg_pdbg("Slow read for partial block from 0x%x, length 0x%x\n",
420 start, residue);
421 ret = spi_read_chunked(flash, buf, start, residue, 16);
Simon Glasse53cc1d2015-01-08 05:48:51 -0700422 if (ret)
423 goto err;
hailfingerfb6287d2010-11-16 21:25:29 +0000424 }
425
426 /* Round down. */
427 bulklen = (len - residue) / chunksize * chunksize;
428 ret = dediprog_spi_bulk_read(flash, buf + residue, start + residue,
429 bulklen);
Simon Glasse53cc1d2015-01-08 05:48:51 -0700430 if (ret)
431 goto err;
hailfingerfb6287d2010-11-16 21:25:29 +0000432
433 len -= residue + bulklen;
434 if (len) {
435 msg_pdbg("Slow read for partial block from 0x%x, length 0x%x\n",
436 start, len);
437 ret = spi_read_chunked(flash, buf + residue + bulklen,
438 start + residue + bulklen, len, 16);
Simon Glasse53cc1d2015-01-08 05:48:51 -0700439 if (ret)
440 goto err;
hailfingerfb6287d2010-11-16 21:25:29 +0000441 }
442
Simon Glasse53cc1d2015-01-08 05:48:51 -0700443 dediprog_set_leds(LED_PASS);
hailfingerfb6287d2010-11-16 21:25:29 +0000444 return 0;
Simon Glasse53cc1d2015-01-08 05:48:51 -0700445err:
446 dediprog_set_leds(LED_ERROR);
447 return ret;
hailfingerdfb32a02010-01-19 11:15:48 +0000448}
449
David Hendricksfe05e742015-08-15 17:29:39 -0700450/* Bulk write interface, will write multiple chunksize byte chunks aligned to chunksize bytes.
451 * @chunksize length of data chunks, only 256 supported by now
452 * @start start address
453 * @len length
454 * @dedi_spi_cmd dediprog specific write command for spi bus
455 * @return 0 on success, 1 on failure
456 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700457static int dediprog_spi_bulk_write(struct flashctx *flash, const uint8_t *buf, unsigned int chunksize,
David Hendricksfe05e742015-08-15 17:29:39 -0700458 unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
hailfinger556e9c32010-11-23 21:28:16 +0000459{
David Hendricksf9ecb452015-11-04 15:40:27 -0800460 int ret, transferred;
David Hendricksfe05e742015-08-15 17:29:39 -0700461 unsigned int i;
462 /* USB transfer size must be 512, other sizes will NOT work at all.
463 * chunksize is the real data size per USB bulk transfer. The remaining
464 * space in a USB bulk transfer must be filled with 0xff padding.
465 */
466 const unsigned int count = len / chunksize;
David Hendricksf9ecb452015-11-04 15:40:27 -0800467 const unsigned char count_and_cmd_old[] = {count & 0xff, (count >> 8) & 0xff, 0x00, dedi_spi_cmd};
468 const unsigned char count_and_cmd_new[] = {
David Hendricks741efe22015-08-15 19:18:51 -0700469 count & 0xff,
470 (count >> 8) & 0xff,
471 0, /* used for 24-bit address support? */
472 dedi_spi_cmd,
473 JEDEC_BYTE_PROGRAM, /* FIXME: needs to be determined based on byte 3? */
474 0,
475 start & 0xff,
476 (start >> 8) & 0xff,
477 (start >> 16) & 0xff,
478 (start >> 24) & 0xff,
479 };
David Hendricksf9ecb452015-11-04 15:40:27 -0800480 unsigned char usbbuf[512];
David Hendricksfe05e742015-08-15 17:29:39 -0700481
482 /*
483 * We should change this check to
484 * chunksize > 512
485 * once we know how to handle different chunk sizes.
486 */
487 if (chunksize != 256) {
488 msg_perr("%s: Chunk sizes other than 256 bytes are unsupported, chunksize=%u!\n"
489 "Please report a bug at flashrom@flashrom.org\n", __func__, chunksize);
490 return 1;
491 }
492
493 if ((start % chunksize) || (len % chunksize)) {
494 msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
495 "at flashrom@flashrom.org\n", __func__, start, len);
496 return 1;
497 }
498
499 /* No idea if the hardware can handle empty writes, so chicken out. */
500 if (!len)
501 return 0;
David Hendricks741efe22015-08-15 19:18:51 -0700502 if (!is_new_prot()) {
503 /* Command Write SPI Bulk. No idea which write command is used on the
504 * SPI side.
505 */
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100506 ret = dediprog_write(CMD_WRITE, start % 0x10000, start / 0x10000,
David Hendricksf9ecb452015-11-04 15:40:27 -0800507 count_and_cmd_old, sizeof(count_and_cmd_old));
David Hendricks741efe22015-08-15 19:18:51 -0700508 if (ret != sizeof(count_and_cmd_old)) {
509 msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret,
David Hendricksf9ecb452015-11-04 15:40:27 -0800510 libusb_error_name(ret));
David Hendricks741efe22015-08-15 19:18:51 -0700511 return 1;
512 }
513 } else {
514 /* Command Write SPI Bulk. No idea which write command is used on the
515 * SPI side.
516 */
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100517 ret = dediprog_write(CMD_WRITE, 0, 0,
David Hendricksf9ecb452015-11-04 15:40:27 -0800518 count_and_cmd_new, sizeof(count_and_cmd_new));
David Hendricks741efe22015-08-15 19:18:51 -0700519 if (ret != sizeof(count_and_cmd_new)) {
520 msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret,
David Hendricksf9ecb452015-11-04 15:40:27 -0800521 libusb_error_name(ret));
David Hendricks741efe22015-08-15 19:18:51 -0700522 return 1;
523 }
David Hendricksfe05e742015-08-15 17:29:39 -0700524 }
525
526 for (i = 0; i < count; i++) {
527 memset(usbbuf, 0xff, sizeof(usbbuf));
528 memcpy(usbbuf, buf + i * chunksize, chunksize);
David Hendricksf9ecb452015-11-04 15:40:27 -0800529 ret = libusb_bulk_transfer(dediprog_handle, dediprog_out_endpoint,
530 usbbuf, 512, &transferred, DEFAULT_TIMEOUT);
531 if ((ret < 0) || (transferred != 512)) {
532 msg_perr("SPI bulk write failed, expected %i, got %i %s!\n",
533 512, ret, libusb_error_name(ret));
David Hendricksfe05e742015-08-15 17:29:39 -0700534 return 1;
535 }
536 }
537
538 return 0;
539}
540
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700541static int dediprog_spi_write(struct flashctx *flash, const uint8_t *buf,
David Hendricksfe05e742015-08-15 17:29:39 -0700542 unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
543{
544 int ret;
Patrick Georgif3fa2992017-02-02 16:24:44 +0100545 const unsigned int chunksize = flash->chip->page_size;
David Hendricksfe05e742015-08-15 17:29:39 -0700546 unsigned int residue = start % chunksize ? chunksize - start % chunksize : 0;
547 unsigned int bulklen;
stepan4c06de72011-01-28 09:00:15 +0000548
Simon Glasse53cc1d2015-01-08 05:48:51 -0700549 dediprog_set_leds(LED_BUSY);
stepan4c06de72011-01-28 09:00:15 +0000550
David Hendricksfe05e742015-08-15 17:29:39 -0700551 if (chunksize != 256) {
552 msg_pdbg("Page sizes other than 256 bytes are unsupported as "
553 "we don't know how dediprog\nhandles them.\n");
554 /* Write everything like it was residue. */
555 residue = len;
556 }
stepan4c06de72011-01-28 09:00:15 +0000557
David Hendricksfe05e742015-08-15 17:29:39 -0700558 if (residue) {
559 msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
560 start, residue);
561 /* No idea about the real limit. Maybe 12, maybe more. */
562 ret = spi_write_chunked(flash, (uint8_t *)buf, start, residue, 12);
563 if (ret) {
564 dediprog_set_leds(LED_ERROR);
565 return ret;
566 }
567 }
568
569 /* Round down. */
570 bulklen = (len - residue) / chunksize * chunksize;
571 ret = dediprog_spi_bulk_write(flash, buf + residue, chunksize, start + residue, bulklen, dedi_spi_cmd);
572 if (ret) {
Simon Glasse53cc1d2015-01-08 05:48:51 -0700573 dediprog_set_leds(LED_ERROR);
David Hendricksfe05e742015-08-15 17:29:39 -0700574 return ret;
575 }
stepan4c06de72011-01-28 09:00:15 +0000576
David Hendricksfe05e742015-08-15 17:29:39 -0700577 len -= residue + bulklen;
578 if (len) {
579 msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
580 start, len);
581 ret = spi_write_chunked(flash, (uint8_t *)(buf + residue + bulklen),
582 start + residue + bulklen, len, 12);
583 if (ret) {
584 dediprog_set_leds(LED_ERROR);
585 return ret;
586 }
587 }
588
589 dediprog_set_leds(LED_PASS);
590 return 0;
hailfinger556e9c32010-11-23 21:28:16 +0000591}
592
Patrick Georgiab8353e2017-02-03 18:32:01 +0100593static int dediprog_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
David Hendricksfe05e742015-08-15 17:29:39 -0700594{
595 return dediprog_spi_write(flash, buf, start, len, WRITE_MODE_PAGE_PGM);
596}
597
598#if 0
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700599static int dediprog_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
David Hendricksfe05e742015-08-15 17:29:39 -0700600{
601 return dediprog_spi_write(flash, buf, start, len, WRITE_MODE_2B_AAI);
602}
603#endif
604
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700605//static int dediprog_spi_send_command(struct flashctx *flash,
606static int dediprog_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
David Hendricksfe05e742015-08-15 17:29:39 -0700607 unsigned int readcnt,
608 const unsigned char *writearr,
609 unsigned char *readarr)
hailfingerdfb32a02010-01-19 11:15:48 +0000610{
611 int ret;
612
hailfingeraf389cc2010-01-22 02:53:30 +0000613 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
David Hendricksfe05e742015-08-15 17:29:39 -0700614 if (writecnt > UINT16_MAX) {
615 msg_perr("Invalid writecnt=%i, aborting.\n", writecnt);
616 return 1;
Simon Glass543101a2015-01-08 06:28:13 -0700617 }
David Hendricksfe05e742015-08-15 17:29:39 -0700618 if (readcnt > UINT16_MAX) {
619 msg_perr("Invalid readcnt=%i, aborting.\n", readcnt);
620 return 1;
621 }
622
David Hendricks14e82e52015-08-15 17:59:03 -0700623 /* New protocol has the read flag as value while the old protocol had it in the index field. */
624 if (is_new_prot()) {
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100625 ret = dediprog_write(CMD_TRANSCEIVE, readcnt ? 1 : 0, 0, writearr, writecnt);
David Hendricks14e82e52015-08-15 17:59:03 -0700626 } else {
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100627 ret = dediprog_write(CMD_TRANSCEIVE, 0, readcnt ? 1 : 0, writearr, writecnt);
David Hendricks14e82e52015-08-15 17:59:03 -0700628 }
hailfingerdfb32a02010-01-19 11:15:48 +0000629 if (ret != writecnt) {
hailfingeraf389cc2010-01-22 02:53:30 +0000630 msg_perr("Send SPI failed, expected %i, got %i %s!\n",
David Hendricksf9ecb452015-11-04 15:40:27 -0800631 writecnt, ret, libusb_error_name(ret));
hailfingerdfb32a02010-01-19 11:15:48 +0000632 return 1;
633 }
David Hendricksfe05e742015-08-15 17:29:39 -0700634 if (readcnt == 0)
hailfingerdfb32a02010-01-19 11:15:48 +0000635 return 0;
David Hendricksfe05e742015-08-15 17:29:39 -0700636
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100637 ret = dediprog_read(CMD_TRANSCEIVE, 0, 0, readarr, readcnt);
hailfingerdfb32a02010-01-19 11:15:48 +0000638 if (ret != readcnt) {
hailfingeraf389cc2010-01-22 02:53:30 +0000639 msg_perr("Receive SPI failed, expected %i, got %i %s!\n",
David Hendricksf9ecb452015-11-04 15:40:27 -0800640 readcnt, ret, libusb_error_name(ret));
hailfingerdfb32a02010-01-19 11:15:48 +0000641 return 1;
642 }
643 return 0;
644}
645
hailfinger1ff33dc2010-07-03 11:02:10 +0000646static int dediprog_check_devicestring(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000647{
648 int ret;
hailfinger7a009082010-11-09 23:30:43 +0000649 int fw[3];
David Hendricks6702e072015-08-15 18:09:04 -0700650 int sfnum;
hailfingerdfb32a02010-01-19 11:15:48 +0000651 char buf[0x11];
652
hailfingerdfb32a02010-01-19 11:15:48 +0000653 /* Command Receive Device String. */
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100654 ret = dediprog_read(CMD_READ_PROG_INFO, 0, 0, (uint8_t *)buf, 0x10);
hailfingerdfb32a02010-01-19 11:15:48 +0000655 if (ret != 0x10) {
656 msg_perr("Incomplete/failed Command Receive Device String!\n");
657 return 1;
658 }
659 buf[0x10] = '\0';
660 msg_pdbg("Found a %s\n", buf);
David Hendricks6702e072015-08-15 18:09:04 -0700661 if (memcmp(buf, "SF100", 0x5) == 0)
662 dediprog_devicetype = DEV_SF100;
663 else if (memcmp(buf, "SF600", 0x5) == 0)
664 dediprog_devicetype = DEV_SF600;
665 else {
David Hendricks22593802015-11-13 12:59:30 -0800666 msg_perr("Device not a SF100 or SF600!\n");
hailfingerdfb32a02010-01-19 11:15:48 +0000667 return 1;
668 }
David Hendricks6702e072015-08-15 18:09:04 -0700669 if (sscanf(buf, "SF%d V:%d.%d.%d ", &sfnum, &fw[0], &fw[1], &fw[2])
670 != 4 || sfnum != dediprog_devicetype) {
David Hendricks14e82e52015-08-15 17:59:03 -0700671 msg_perr("Unexpected firmware version string '%s'\n", buf);
hailfinger7a009082010-11-09 23:30:43 +0000672 return 1;
673 }
David Hendricks14e82e52015-08-15 17:59:03 -0700674 /* Only these major versions were tested. */
David Hendricks6702e072015-08-15 18:09:04 -0700675 if (fw[0] < 2 || fw[0] > 7) {
David Hendricks14e82e52015-08-15 17:59:03 -0700676 msg_perr("Unexpected firmware version %d.%d.%d!\n", fw[0], fw[1], fw[2]);
hailfingerdfb32a02010-01-19 11:15:48 +0000677 return 1;
678 }
stepan4c06de72011-01-28 09:00:15 +0000679 dediprog_firmwareversion = FIRMWARE_VERSION(fw[0], fw[1], fw[2]);
David Hendricks14e82e52015-08-15 17:59:03 -0700680
hailfingerdfb32a02010-01-19 11:15:48 +0000681 return 0;
682}
683
David Hendricks91ca7ac2015-11-20 16:22:22 -0800684static int dediprog_supply_voltages[] = {
685 0, 1800, 2500, 3500,
686};
687
688static int dediprog_set_spi_flash_voltage_manual(int millivolt)
689{
690 int ret;
691 uint16_t voltage_selector;
692
693 switch (millivolt) {
694 case 0:
695 /* Admittedly this one is an assumption. */
696 voltage_selector = 0x0;
697 break;
698 case 1800:
699 voltage_selector = 0x12;
700 break;
701 case 2500:
702 voltage_selector = 0x11;
703 break;
704 case 3500:
705 voltage_selector = 0x10;
706 break;
707 default:
708 msg_perr("Unknown voltage %i mV! Aborting.\n", millivolt);
709 return 1;
710 }
711 msg_pdbg("Setting SPI voltage to %u.%03u V\n", millivolt / 1000,
712 millivolt % 1000);
713
714 if (voltage_selector == 0) {
715 /* Wait some time as the original driver does. */
716 programmer_delay(200 * 1000);
717 }
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100718 ret = dediprog_write(CMD_SET_VCC, voltage_selector, 0, NULL, 0);
David Hendricks91ca7ac2015-11-20 16:22:22 -0800719 if (ret != 0x0) {
720 msg_perr("Command Set SPI Voltage 0x%x failed!\n",
721 voltage_selector);
722 return 1;
723 }
724 if (voltage_selector != 0) {
725 /* Wait some time as the original driver does. */
726 programmer_delay(200 * 1000);
727 }
728 return 0;
729}
730
David Hendricks93784b42016-08-09 17:00:38 -0700731static int dediprog_set_spi_flash_voltage_auto(void)
David Hendricks91ca7ac2015-11-20 16:22:22 -0800732{
David Hendricksac1d25c2016-08-09 17:00:58 -0700733 int i;
David Hendricks91ca7ac2015-11-20 16:22:22 -0800734 int spi_flash_ranges;
735
736 spi_flash_ranges = flash_supported_voltage_ranges(BUS_SPI);
737 if (spi_flash_ranges < 0)
738 return -1;
739
740 for (i = 0; i < ARRAY_SIZE(dediprog_supply_voltages); i++) {
741 int j;
742 int v = dediprog_supply_voltages[i]; /* shorthand */
743
744 for (j = 0; j < spi_flash_ranges; j++) {
745 /* Dediprog can supply a voltage in this range. */
746 if ((v >= voltage_ranges[j].min) && (v <= voltage_ranges[j].max)) {
David Hendricks93784b42016-08-09 17:00:38 -0700747 struct flashctx dummy;
748
David Hendricks91ca7ac2015-11-20 16:22:22 -0800749 msg_cdbg("%s: trying %d\n", __func__, v);
750 if (dediprog_set_spi_flash_voltage_manual(v)) {
751 msg_cerr("%s: Failed to set SPI voltage\n", __func__);
752 return 1;
753 }
754
755 clear_spi_id_cache();
David Hendricksac1d25c2016-08-09 17:00:58 -0700756 if (probe_flash(0, &dummy, 0) < 0) {
David Hendricks91ca7ac2015-11-20 16:22:22 -0800757 /* No dice, try next voltage supported by Dediprog. */
758 break;
759 }
760
Patrick Georgif3fa2992017-02-02 16:24:44 +0100761 if ((dummy.chip->manufacture_id == GENERIC_MANUF_ID) ||
762 (dummy.chip->model_id == GENERIC_DEVICE_ID)) {
David Hendricks91ca7ac2015-11-20 16:22:22 -0800763 break;
764 }
765
766 return 0;
767 }
768 }
769 }
770
771 return 1;
772}
773
774/* FIXME: ugly function signature */
David Hendricks93784b42016-08-09 17:00:38 -0700775static int dediprog_set_spi_voltage(int millivolt, int probe)
David Hendricks91ca7ac2015-11-20 16:22:22 -0800776{
777 if (probe)
David Hendricks93784b42016-08-09 17:00:38 -0700778 return dediprog_set_spi_flash_voltage_auto();
David Hendricks91ca7ac2015-11-20 16:22:22 -0800779 else
780 return dediprog_set_spi_flash_voltage_manual(millivolt);
781}
782
David Hendricks28fbdfb2015-08-15 18:04:37 -0700783/*
784 * This command presumably sets the voltage for the SF100 itself (not the
785 * SPI flash). Only use this command with firmware older than V6.0.0. Newer
786 * (including all SF600s) do not support it.
787 */
788static int dediprog_set_voltage(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000789{
790 int ret;
David Hendricksf9ecb452015-11-04 15:40:27 -0800791 unsigned char buf[0x1];
hailfingerdfb32a02010-01-19 11:15:48 +0000792
793 memset(buf, 0, sizeof(buf));
David Hendricksa7f99ac2015-11-12 16:42:03 -0800794 ret = dediprog_read_other(CMD_SET_VOLTAGE, 0x0, 0x0, buf, 0x1);
hailfinger7a009082010-11-09 23:30:43 +0000795 if (ret < 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800796 msg_perr("Command A failed (%s)!\n", libusb_error_name(ret));
hailfinger7a009082010-11-09 23:30:43 +0000797 return 1;
798 }
hailfingerdfb32a02010-01-19 11:15:48 +0000799 if ((ret != 0x1) || (buf[0] != 0x6f)) {
Simon Glassa1f80682015-01-08 05:55:29 -0700800 msg_perr("Unexpected response to init!\n");
hailfingerdfb32a02010-01-19 11:15:48 +0000801 return 1;
802 }
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100803
hailfingerdfb32a02010-01-19 11:15:48 +0000804 return 0;
805}
806
David Hendrickscf453d82015-11-16 20:19:57 -0800807static int dediprog_leave_standalone_mode(void)
808{
809 int ret;
810
811 if (dediprog_devicetype != DEV_SF600)
812 return 0;
813
814 msg_pdbg("Leaving standalone mode\n");
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100815 ret = dediprog_write(CMD_SET_STANDALONE, LEAVE_STANDALONE_MODE, 0, NULL, 0);
David Hendrickscf453d82015-11-16 20:19:57 -0800816 if (ret) {
817 msg_perr("Failed to leave standalone mode (%s)!\n", libusb_error_name(ret));
818 return 1;
819 }
820
821 return 0;
822}
823
David Hendricksfe05e742015-08-15 17:29:39 -0700824static int set_target_flash(enum dediprog_target target)
825{
Edward O'Callaghan0ea95ea2019-02-27 22:17:15 +1100826 int ret = dediprog_write(CMD_SET_TARGET, target, 0, NULL, 0);
David Hendricksfe05e742015-08-15 17:29:39 -0700827 if (ret != 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800828 msg_perr("set_target_flash failed (%s)!\n", libusb_error_name(ret));
hailfingerdfb32a02010-01-19 11:15:48 +0000829 return 1;
830 }
831 return 0;
832}
833
David Hendricksfe05e742015-08-15 17:29:39 -0700834#if 0
835/* Returns true if the button is currently pressed. */
836static bool dediprog_get_button(void)
Simon Glassd01002b2015-01-08 05:44:16 -0700837{
David Hendricksfe05e742015-08-15 17:29:39 -0700838 char buf[1];
839 int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_GET_BUTTON, 0, 0,
840 buf, 0x1, DEFAULT_TIMEOUT);
841 if (ret != 0) {
842 msg_perr("Could not get button state (%s)!\n", usb_strerror());
843 return 1;
Simon Glassd01002b2015-01-08 05:44:16 -0700844 }
David Hendricksfe05e742015-08-15 17:29:39 -0700845 return buf[0] != 1;
Simon Glassd01002b2015-01-08 05:44:16 -0700846}
David Hendricksfe05e742015-08-15 17:29:39 -0700847#endif
Simon Glassd01002b2015-01-08 05:44:16 -0700848
hailfingerf76cc322010-11-09 22:00:31 +0000849static int parse_voltage(char *voltage)
850{
851 char *tmp = NULL;
hailfingerb91c08c2011-08-15 19:54:20 +0000852 int i;
853 int millivolt = 0, fraction = 0;
hailfingerf76cc322010-11-09 22:00:31 +0000854
855 if (!voltage || !strlen(voltage)) {
856 msg_perr("Empty voltage= specified.\n");
857 return -1;
858 }
859 millivolt = (int)strtol(voltage, &tmp, 0);
860 voltage = tmp;
861 /* Handle "," and "." as decimal point. Everything after it is assumed
862 * to be in decimal notation.
863 */
864 if ((*voltage == '.') || (*voltage == ',')) {
865 voltage++;
866 for (i = 0; i < 3; i++) {
867 fraction *= 10;
868 /* Don't advance if the current character is invalid,
869 * but continue multiplying.
870 */
871 if ((*voltage < '0') || (*voltage > '9'))
872 continue;
873 fraction += *voltage - '0';
874 voltage++;
875 }
876 /* Throw away remaining digits. */
877 voltage += strspn(voltage, "0123456789");
878 }
879 /* The remaining string must be empty or "mV" or "V". */
880 tolower_string(voltage);
881
882 /* No unit or "V". */
883 if ((*voltage == '\0') || !strncmp(voltage, "v", 1)) {
884 millivolt *= 1000;
885 millivolt += fraction;
886 } else if (!strncmp(voltage, "mv", 2) ||
887 !strncmp(voltage, "milliv", 6)) {
888 /* No adjustment. fraction is discarded. */
889 } else {
890 /* Garbage at the end of the string. */
891 msg_perr("Garbage voltage= specified.\n");
892 return -1;
893 }
894 return millivolt;
895}
896
David Hendricksfe05e742015-08-15 17:29:39 -0700897#if 0
898static const struct spi_master spi_master_dediprog = {
899 .type = SPI_CONTROLLER_DEDIPROG,
900 .max_data_read = MAX_DATA_UNSPECIFIED,
901 .max_data_write = MAX_DATA_UNSPECIFIED,
902 .command = dediprog_spi_send_command,
903 .multicommand = default_spi_send_multicommand,
904 .read = dediprog_spi_read,
905 .write_256 = dediprog_spi_write_256,
906 .write_aai = dediprog_spi_write_aai,
907};
908#endif
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100909static const struct spi_master spi_master_dediprog = {
uwe8d342eb2011-07-28 08:13:25 +0000910 .type = SPI_CONTROLLER_DEDIPROG,
911 .max_data_read = MAX_DATA_UNSPECIFIED,
912 .max_data_write = MAX_DATA_UNSPECIFIED,
913 .command = dediprog_spi_send_command,
914 .multicommand = default_spi_send_multicommand,
915 .read = dediprog_spi_read,
916 .write_256 = dediprog_spi_write_256,
mkarcherd264e9e2011-05-11 17:07:07 +0000917};
918
David Hendricks93784b42016-08-09 17:00:38 -0700919static int dediprog_shutdown(void *data)
dhendrix0ffc2eb2011-06-14 01:35:36 +0000920{
921 msg_pspew("%s\n", __func__);
922
David Hendricksfe05e742015-08-15 17:29:39 -0700923 dediprog_firmwareversion = FIRMWARE_VERSION(0, 0, 0);
David Hendricks6702e072015-08-15 18:09:04 -0700924 dediprog_devicetype = DEV_UNKNOWN;
David Hendricksfe05e742015-08-15 17:29:39 -0700925
dhendrix0ffc2eb2011-06-14 01:35:36 +0000926 /* URB 28. Command Set SPI Voltage to 0. */
David Hendricks93784b42016-08-09 17:00:38 -0700927 if (dediprog_set_spi_voltage(0x0, 0))
dhendrix0ffc2eb2011-06-14 01:35:36 +0000928 return 1;
929
David Hendricksf9ecb452015-11-04 15:40:27 -0800930 if (libusb_release_interface(dediprog_handle, 0)) {
dhendrix0ffc2eb2011-06-14 01:35:36 +0000931 msg_perr("Could not release USB interface!\n");
932 return 1;
933 }
David Hendricksf9ecb452015-11-04 15:40:27 -0800934 libusb_close(dediprog_handle);
935 libusb_exit(usb_ctx);
936
dhendrix0ffc2eb2011-06-14 01:35:36 +0000937 return 0;
938}
939
hailfingerdfb32a02010-01-19 11:15:48 +0000940/* URB numbers refer to the first log ever captured. */
David Hendricksac1d25c2016-08-09 17:00:58 -0700941int dediprog_init(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000942{
David Hendricks98b3c572016-11-30 01:50:08 +0000943 char *voltage, *device, *spispeed, *target_str;
David Hendricksfe05e742015-08-15 17:29:39 -0700944 int spispeed_idx = 1;
David Hendrickscd20ea42015-11-17 22:33:35 -0800945 int millivolt = 0;
David Hendricksfe05e742015-08-15 17:29:39 -0700946 long usedevice = 0;
947 long target = 1;
David Hendricks98b3c572016-11-30 01:50:08 +0000948 int i, ret;
hailfingerdfb32a02010-01-19 11:15:48 +0000949
950 msg_pspew("%s\n", __func__);
951
David Hendricksfe05e742015-08-15 17:29:39 -0700952 spispeed = extract_programmer_param("spispeed");
953 if (spispeed) {
954 for (i = 0; spispeeds[i].name; ++i) {
955 if (!strcasecmp(spispeeds[i].name, spispeed)) {
956 spispeed_idx = i;
957 break;
958 }
959 }
960 if (!spispeeds[i].name) {
961 msg_perr("Error: Invalid spispeed value: '%s'.\n", spispeed);
David Hendricks98b3c572016-11-30 01:50:08 +0000962 free(spispeed);
963 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -0700964 }
David Hendricks98b3c572016-11-30 01:50:08 +0000965 free(spispeed);
David Hendricksfe05e742015-08-15 17:29:39 -0700966 }
967
hailfingerf76cc322010-11-09 22:00:31 +0000968 voltage = extract_programmer_param("voltage");
969 if (voltage) {
970 millivolt = parse_voltage(voltage);
971 free(voltage);
David Hendricks98b3c572016-11-30 01:50:08 +0000972 if (millivolt < 0)
973 return 1;
hailfingerf76cc322010-11-09 22:00:31 +0000974 msg_pinfo("Setting voltage to %i mV\n", millivolt);
975 }
David Hendricksfe05e742015-08-15 17:29:39 -0700976
977 device = extract_programmer_param("device");
978 if (device) {
979 char *dev_suffix;
980 errno = 0;
981 usedevice = strtol(device, &dev_suffix, 10);
982 if (errno != 0 || device == dev_suffix) {
983 msg_perr("Error: Could not convert 'device'.\n");
David Hendricks98b3c572016-11-30 01:50:08 +0000984 free(device);
985 return 1;
Simon Glassd01002b2015-01-08 05:44:16 -0700986 }
David Hendricksfe05e742015-08-15 17:29:39 -0700987 if (usedevice < 0 || usedevice > UINT_MAX) {
988 msg_perr("Error: Value for 'device' is out of range.\n");
David Hendricks98b3c572016-11-30 01:50:08 +0000989 free(device);
990 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -0700991 }
992 if (strlen(dev_suffix) > 0) {
993 msg_perr("Error: Garbage following 'device' value.\n");
David Hendricks98b3c572016-11-30 01:50:08 +0000994 free(device);
995 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -0700996 }
997 msg_pinfo("Using device %li.\n", usedevice);
Simon Glassd01002b2015-01-08 05:44:16 -0700998 }
David Hendricks98b3c572016-11-30 01:50:08 +0000999 free(device);
David Hendricksfe05e742015-08-15 17:29:39 -07001000
1001 target_str = extract_programmer_param("target");
1002 if (target_str) {
1003 char *target_suffix;
1004 errno = 0;
1005 target = strtol(target_str, &target_suffix, 10);
1006 if (errno != 0 || target_str == target_suffix) {
1007 msg_perr("Error: Could not convert 'target'.\n");
David Hendricks98b3c572016-11-30 01:50:08 +00001008 free(target_str);
1009 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -07001010 }
1011 if (target < 1 || target > 2) {
1012 msg_perr("Error: Value for 'target' is out of range.\n");
David Hendricks98b3c572016-11-30 01:50:08 +00001013 free(target_str);
1014 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -07001015 }
1016 if (strlen(target_suffix) > 0) {
1017 msg_perr("Error: Garbage following 'target' value.\n");
David Hendricks98b3c572016-11-30 01:50:08 +00001018 free(target_str);
1019 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -07001020 }
1021 msg_pinfo("Using target %li.\n", target);
1022 }
David Hendricks98b3c572016-11-30 01:50:08 +00001023 free(target_str);
hailfingerf76cc322010-11-09 22:00:31 +00001024
hailfingerdfb32a02010-01-19 11:15:48 +00001025 /* Here comes the USB stuff. */
David Hendricksf9ecb452015-11-04 15:40:27 -08001026 libusb_init(&usb_ctx);
1027 if (!usb_ctx) {
1028 msg_perr("Could not initialize libusb!\n");
David Hendricks98b3c572016-11-30 01:50:08 +00001029 return 1;
hailfingerdfb32a02010-01-19 11:15:48 +00001030 }
Edward O'Callaghana88395f2019-02-27 18:44:04 +11001031 const uint16_t vid = devs_dediprog[0].vendor_id;
1032 const uint16_t pid = devs_dediprog[0].device_id;
1033 dediprog_handle = usb_dev_get_by_vid_pid_number(usb_ctx, vid, pid, (unsigned int) usedevice);
David Hendricksfe05e742015-08-15 17:29:39 -07001034 if (!dediprog_handle) {
David Hendricks22593802015-11-13 12:59:30 -08001035 msg_perr("Could not find a Dediprog programmer on USB!\n");
David Hendricksf9ecb452015-11-04 15:40:27 -08001036 libusb_exit(usb_ctx);
David Hendricks98b3c572016-11-30 01:50:08 +00001037 return 1;
David Hendricksfe05e742015-08-15 17:29:39 -07001038 }
David Hendricks98b3c572016-11-30 01:50:08 +00001039 ret = libusb_set_configuration(dediprog_handle, 1);
1040 if (ret != 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -08001041 msg_perr("Could not set USB device configuration: %i %s\n", ret, libusb_error_name(ret));
1042 libusb_close(dediprog_handle);
1043 libusb_exit(usb_ctx);
David Hendricks98b3c572016-11-30 01:50:08 +00001044 return 1;
hailfingerfb6287d2010-11-16 21:25:29 +00001045 }
David Hendricks98b3c572016-11-30 01:50:08 +00001046 ret = libusb_claim_interface(dediprog_handle, 0);
1047 if (ret < 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -08001048 msg_perr("Could not claim USB device interface %i: %i %s\n", 0, ret, libusb_error_name(ret));
1049 libusb_close(dediprog_handle);
1050 libusb_exit(usb_ctx);
David Hendricks98b3c572016-11-30 01:50:08 +00001051 return 1;
hailfingerfb6287d2010-11-16 21:25:29 +00001052 }
David Hendricksfe05e742015-08-15 17:29:39 -07001053
David Hendricks98b3c572016-11-30 01:50:08 +00001054 if (register_shutdown(dediprog_shutdown, NULL))
1055 return 1;
dhendrix0ffc2eb2011-06-14 01:35:36 +00001056
David Hendricks28fbdfb2015-08-15 18:04:37 -07001057 /* Try reading the devicestring. If that fails and the device is old
1058 * (FW < 6.0.0) then we need to try the "set voltage" command and then
1059 * attempt to read the devicestring again. */
1060 if (dediprog_check_devicestring()) {
David Hendricks98b3c572016-11-30 01:50:08 +00001061 if (dediprog_set_voltage())
1062 return 1;
1063 if (dediprog_check_devicestring())
1064 return 1;
David Hendricks28fbdfb2015-08-15 18:04:37 -07001065 }
David Hendricksfe05e742015-08-15 17:29:39 -07001066
David Hendricksd7468582015-11-12 15:21:12 -08001067 /* SF100 firmware exposes only one endpoint for in/out, SF600 firmware
1068 exposes separate endpoints for in and out. */
1069 dediprog_in_endpoint = 2;
1070 if (dediprog_devicetype == DEV_SF100)
1071 dediprog_out_endpoint = 2;
1072 else
1073 dediprog_out_endpoint = 1;
1074
David Hendricks93784b42016-08-09 17:00:38 -07001075
David Hendrickse4c73662015-11-20 16:26:07 -08001076 /* Set some LEDs as soon as possible to indicate activity.
David Hendricksfe05e742015-08-15 17:29:39 -07001077 * Because knowing the firmware version is required to set the LEDs correctly we need to this after
1078 * dediprog_setup() has queried the device and set dediprog_firmwareversion. */
David Hendrickse4c73662015-11-20 16:26:07 -08001079 dediprog_set_leds(LED_PASS | LED_BUSY);
David Hendricksfe05e742015-08-15 17:29:39 -07001080
David Hendrickscd20ea42015-11-17 22:33:35 -08001081 /* FIXME: need to do this so buses_supported gets SPI */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01001082 register_spi_master(&spi_master_dediprog);
David Hendricks93784b42016-08-09 17:00:38 -07001083
David Hendricksfe05e742015-08-15 17:29:39 -07001084 /* Select target/socket, frequency and VCC. */
1085 if (set_target_flash(FLASH_TYPE_APPLICATION_FLASH_1) ||
1086 dediprog_set_spi_speed(spispeed_idx) ||
David Hendricks93784b42016-08-09 17:00:38 -07001087 dediprog_set_spi_voltage(millivolt, voltage ? 0 : 1)) {
Simon Glasse53cc1d2015-01-08 05:48:51 -07001088 dediprog_set_leds(LED_ERROR);
David Hendricks98b3c572016-11-30 01:50:08 +00001089 return 1;
stepan4c06de72011-01-28 09:00:15 +00001090 }
hailfingerdfb32a02010-01-19 11:15:48 +00001091
David Hendricks98b3c572016-11-30 01:50:08 +00001092 if (dediprog_leave_standalone_mode())
1093 return 1;
1094
David Hendricks93784b42016-08-09 17:00:38 -07001095
David Hendricksfe05e742015-08-15 17:29:39 -07001096 dediprog_set_leds(LED_NONE);
stepan4c06de72011-01-28 09:00:15 +00001097
David Hendricks98b3c572016-11-30 01:50:08 +00001098 return 0;
hailfingerdfb32a02010-01-19 11:15:48 +00001099}