blob: eaca35b8982d32c23f68342f23b7e88397cecb7f [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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
David Hendricksfe05e742015-08-15 17:29:39 -070022//#include "platform.h"
23
24#include <stdlib.h>
hailfinger7a009082010-11-09 23:30:43 +000025#include <stdio.h>
hailfingerdfb32a02010-01-19 11:15:48 +000026#include <string.h>
David Hendricksfe05e742015-08-15 17:29:39 -070027#include <limits.h>
28#include <errno.h>
29
30#if IS_WINDOWS
31#include <lusb0_usb.h>
32#else
David Hendricksf9ecb452015-11-04 15:40:27 -080033#include <libusb.h>
David Hendricksfe05e742015-08-15 17:29:39 -070034#endif
35
hailfingerdfb32a02010-01-19 11:15:48 +000036#include "flash.h"
David Hendrickscd20ea42015-11-17 22:33:35 -080037#include "flashchips.h"
snelson8913d082010-02-26 05:48:29 +000038#include "chipdrivers.h"
hailfinger428f6852010-07-27 22:41:39 +000039#include "programmer.h"
hailfingerdfb32a02010-01-19 11:15:48 +000040#include "spi.h"
41
stepan4c06de72011-01-28 09:00:15 +000042#define FIRMWARE_VERSION(x,y,z) ((x << 16) | (y << 8) | z)
hailfingerdfb32a02010-01-19 11:15:48 +000043#define DEFAULT_TIMEOUT 3000
David Hendricksf9ecb452015-11-04 15:40:27 -080044#define DEDIPROG_ASYNC_TRANSFERS 8 /* at most 8 asynchronous transfers */
45#define REQTYPE_OTHER_OUT (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0x43 */
46#define REQTYPE_OTHER_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0xC3 */
47#define REQTYPE_EP_OUT (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0x42 */
48#define REQTYPE_EP_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0xC2 */
49struct libusb_context *usb_ctx;
50static libusb_device_handle *dediprog_handle;
David Hendricksd7468582015-11-12 15:21:12 -080051static int dediprog_in_endpoint;
52static int dediprog_out_endpoint;
David Hendricksf9ecb452015-11-04 15:40:27 -080053static int dediprog_firmwareversion = FIRMWARE_VERSION(0, 0, 0);
hailfingerdfb32a02010-01-19 11:15:48 +000054
David Hendricks6702e072015-08-15 18:09:04 -070055enum dediprog_devtype {
56 DEV_UNKNOWN = 0,
57 DEV_SF100 = 100,
58 DEV_SF600 = 600,
59};
60
61enum dediprog_devtype dediprog_devicetype;
62
David Hendricksfe05e742015-08-15 17:29:39 -070063enum dediprog_leds {
64 LED_INVALID = -1,
65 LED_NONE = 0,
Simon Glasse53cc1d2015-01-08 05:48:51 -070066 LED_PASS = 1 << 0,
67 LED_BUSY = 1 << 1,
68 LED_ERROR = 1 << 2,
69 LED_ALL = 7,
70};
71
Simon Glassa1f80682015-01-08 05:55:29 -070072/* IO bits for CMD_SET_IO_LED message */
David Hendricksfe05e742015-08-15 17:29:39 -070073enum dediprog_ios {
Simon Glassa1f80682015-01-08 05:55:29 -070074 IO1 = 1 << 0,
75 IO2 = 1 << 1,
76 IO3 = 1 << 2,
77 IO4 = 1 << 3,
78};
79
David Hendricksfe05e742015-08-15 17:29:39 -070080enum dediprog_cmds {
81 CMD_TRANSCEIVE = 0x01,
82 CMD_POLL_STATUS_REG = 0x02,
83 CMD_SET_VPP = 0x03,
84 CMD_SET_TARGET = 0x04,
85 CMD_READ_EEPROM = 0x05,
86 CMD_WRITE_EEPROM = 0x06,
87 CMD_SET_IO_LED = 0x07,
88 CMD_READ_PROG_INFO = 0x08,
89 CMD_SET_VCC = 0x09,
90 CMD_SET_STANDALONE = 0x0A,
David Hendricks28fbdfb2015-08-15 18:04:37 -070091 CMD_SET_VOLTAGE = 0x0B, /* Only in firmware older than 6.0.0 */
David Hendricksfe05e742015-08-15 17:29:39 -070092 CMD_GET_BUTTON = 0x11,
93 CMD_GET_UID = 0x12,
94 CMD_SET_CS = 0x14,
95 CMD_IO_MODE = 0x15,
96 CMD_FW_UPDATE = 0x1A,
97 CMD_FPGA_UPDATE = 0x1B,
98 CMD_READ_FPGA_VERSION = 0x1C,
99 CMD_SET_HOLD = 0x1D,
100 CMD_READ = 0x20,
101 CMD_WRITE = 0x30,
102 CMD_WRITE_AT45DB = 0x31,
103 CMD_NAND_WRITE = 0x32,
104 CMD_NAND_READ = 0x33,
105 CMD_SET_SPI_CLK = 0x61,
106 CMD_CHECK_SOCKET = 0x62,
107 CMD_DOWNLOAD_PRJ = 0x63,
108 CMD_READ_PRJ_NAME = 0x64,
109 // New protocol/firmware only
110 CMD_CHECK_SDCARD = 0x65,
111 CMD_READ_PRJ = 0x66,
Simon Glassa1f80682015-01-08 05:55:29 -0700112};
113
David Hendricksfe05e742015-08-15 17:29:39 -0700114enum dediprog_target {
115 FLASH_TYPE_APPLICATION_FLASH_1 = 0,
116 FLASH_TYPE_FLASH_CARD,
117 FLASH_TYPE_APPLICATION_FLASH_2,
118 FLASH_TYPE_SOCKET,
Simon Glassa1f80682015-01-08 05:55:29 -0700119};
120
David Hendricksfe05e742015-08-15 17:29:39 -0700121enum dediprog_readmode {
122 READ_MODE_STD = 1,
123 READ_MODE_FAST = 2,
124 READ_MODE_ATMEL45 = 3,
125 READ_MODE_4B_ADDR_FAST = 4,
126 READ_MODE_4B_ADDR_FAST_0x0C = 5, /* New protocol only */
Simon Glassd01002b2015-01-08 05:44:16 -0700127};
128
David Hendricksfe05e742015-08-15 17:29:39 -0700129enum dediprog_writemode {
130 WRITE_MODE_PAGE_PGM = 1,
131 WRITE_MODE_PAGE_WRITE = 2,
132 WRITE_MODE_1B_AAI = 3,
133 WRITE_MODE_2B_AAI = 4,
134 WRITE_MODE_128B_PAGE = 5,
135 WRITE_MODE_PAGE_AT26DF041 = 6,
136 WRITE_MODE_SILICON_BLUE_FPGA = 7,
137 WRITE_MODE_64B_PAGE_NUMONYX_PCM = 8, /* unit of length 512 bytes */
138 WRITE_MODE_4B_ADDR_256B_PAGE_PGM = 9,
139 WRITE_MODE_32B_PAGE_PGM_MXIC_512K = 10, /* unit of length 512 bytes */
140 WRITE_MODE_4B_ADDR_256B_PAGE_PGM_0x12 = 11,
141 WRITE_MODE_4B_ADDR_256B_PAGE_PGM_FLAGS = 12,
Simon Glassd01002b2015-01-08 05:44:16 -0700142};
143
David Hendrickscf453d82015-11-16 20:19:57 -0800144enum dediprog_standalone_mode {
145 ENTER_STANDALONE_MODE = 0,
146 LEAVE_STANDALONE_MODE = 1,
147};
148
David Hendricksf9ecb452015-11-04 15:40:27 -0800149#ifndef LIBUSB_HAVE_ERROR_NAME
150/* Quick and dirty replacement for missing libusb_error_name in older libusb 1.0. */
151const char *libusb_error_name(int error_code)
152{
153 /* 18 chars for text, rest for number, sign, nullbyte. */
154 static char my_libusb_error[18 + 6];
David Hendricksfe05e742015-08-15 17:29:39 -0700155
David Hendricksf9ecb452015-11-04 15:40:27 -0800156 sprintf(my_libusb_error, "libusb error code %i", error_code);
157 return my_libusb_error;
158}
159#endif
David Hendricksfe05e742015-08-15 17:29:39 -0700160
David Hendricks14e82e52015-08-15 17:59:03 -0700161/* Returns true if firmware (and thus hardware) supports the "new" protocol */
162static int is_new_prot(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000163{
David Hendricks6702e072015-08-15 18:09:04 -0700164 switch (dediprog_devicetype) {
165 case DEV_SF100:
166 return dediprog_firmwareversion >= FIRMWARE_VERSION(5, 5, 0);
167 case DEV_SF600:
168 return dediprog_firmwareversion >= FIRMWARE_VERSION(6, 9, 0);
169 default:
170 return 0;
171 }
hailfingerdfb32a02010-01-19 11:15:48 +0000172}
David Hendricks14e82e52015-08-15 17:59:03 -0700173
David Hendricksf9ecb452015-11-04 15:40:27 -0800174struct dediprog_transfer_status {
175 int error; /* OK if 0, ERROR else */
176 unsigned int queued_idx;
177 unsigned int finished_idx;
178};
179
180static void dediprog_bulk_read_cb(struct libusb_transfer *const transfer)
181{
182 struct dediprog_transfer_status *const status = (struct dediprog_transfer_status *)transfer->user_data;
183 if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
184 status->error = 1;
185 msg_perr("SPI bulk read failed!\n");
186 }
187 ++status->finished_idx;
188}
189
190static int dediprog_bulk_read_poll(const struct dediprog_transfer_status *const status, const int finish)
191{
192 if (status->finished_idx >= status->queued_idx)
193 return 0;
194
195 do {
196 struct timeval timeout = { 10, 0 };
197 const int ret = libusb_handle_events_timeout_completed(usb_ctx, &timeout, NULL);
198 if (ret < 0) {
199 msg_perr("Polling read events failed: %i %s!\n", ret, libusb_error_name(ret));
200 return 1;
201 }
202 } while (finish && (status->finished_idx < status->queued_idx));
203 return 0;
204}
205
David Hendricksa7f99ac2015-11-12 16:42:03 -0800206static int dediprog_read_ep(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, uint8_t *bytes, size_t size)
David Hendricks14e82e52015-08-15 17:59:03 -0700207{
David Hendricksf9ecb452015-11-04 15:40:27 -0800208 return libusb_control_transfer(dediprog_handle, REQTYPE_EP_IN, cmd, value, idx,
209 (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
David Hendricks14e82e52015-08-15 17:59:03 -0700210}
211
David Hendricksa7f99ac2015-11-12 16:42:03 -0800212static int dediprog_write_ep(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size)
David Hendricks14e82e52015-08-15 17:59:03 -0700213{
David Hendricksf9ecb452015-11-04 15:40:27 -0800214 return libusb_control_transfer(dediprog_handle, REQTYPE_EP_OUT, cmd, value, idx,
215 (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
David Hendricks14e82e52015-08-15 17:59:03 -0700216}
hailfingerdfb32a02010-01-19 11:15:48 +0000217
David Hendricksa7f99ac2015-11-12 16:42:03 -0800218static int dediprog_read_other(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size)
219{
220 return libusb_control_transfer(dediprog_handle, REQTYPE_OTHER_IN, cmd, value, idx,
221 (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
222}
David Hendricksf9ecb452015-11-04 15:40:27 -0800223
224#if 0
hailfinger1ff33dc2010-07-03 11:02:10 +0000225/* Might be useful for other USB devices as well. static for now. */
David Hendricksfe05e742015-08-15 17:29:39 -0700226/* device parameter allows user to specify one device of multiple installed */
227static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device)
hailfingerdfb32a02010-01-19 11:15:48 +0000228{
229 struct usb_bus *bus;
230 struct usb_device *dev;
231
232 for (bus = usb_get_busses(); bus; bus = bus->next)
233 for (dev = bus->devices; dev; dev = dev->next)
234 if ((dev->descriptor.idVendor == vid) &&
David Hendricksfe05e742015-08-15 17:29:39 -0700235 (dev->descriptor.idProduct == pid)) {
236 if (device == 0)
237 return dev;
238 device--;
239 }
hailfingerdfb32a02010-01-19 11:15:48 +0000240
241 return NULL;
242}
David Hendricksf9ecb452015-11-04 15:40:27 -0800243#endif
244
245/* Might be useful for other USB devices as well. static for now. */
246/* device parameter allows user to specify one device of multiple installed */
247static struct libusb_device_handle *get_device_by_vid_pid_number(uint16_t vid, uint16_t pid, unsigned int num)
248{
249 struct libusb_device **list;
250 ssize_t i = 0;
251 int err = 0;
252 struct libusb_device_handle *handle = NULL;
253 struct libusb_device_descriptor desc = {};
254 ssize_t count = libusb_get_device_list(usb_ctx, &list);
255
256 if (count < 0) {
257 msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count));
258 return NULL;
259 }
260
261 for (i = 0; i < count; i++) {
262 struct libusb_device *dev = list[i];
263 err = libusb_get_device_descriptor(dev, &desc);
264 if (err != 0) {
265 msg_perr("Reading the USB device descriptor failed (%s)!\n", libusb_error_name(err));
266 libusb_free_device_list(list, 1);
267 return NULL;
268 }
269 if ((desc.idVendor == vid) && (desc.idProduct == pid)) {
270 msg_pdbg("Found USB device %04hx:%04hx at address %hhx-%hhx.\n", desc.idVendor,
271 desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev));
272 if (num == 0) {
273 err = libusb_open(dev, &handle);
274 if (err != 0) {
275 msg_perr("Opening the USB device failed (%s)!\n",
276 libusb_error_name(err));
277 libusb_free_device_list(list, 1);
278 return NULL;
279 }
280 break;
281 }
282 num--;
283 }
284 }
285 libusb_free_device_list(list, 1);
286
287 return handle;
288}
hailfingerdfb32a02010-01-19 11:15:48 +0000289
David Hendricksfe05e742015-08-15 17:29:39 -0700290/* This function sets the GPIOs connected to the LEDs as well as IO1-IO4. */
stepan4c06de72011-01-28 09:00:15 +0000291static int dediprog_set_leds(int leds)
292{
David Hendricksfe05e742015-08-15 17:29:39 -0700293 if (leds < LED_NONE || leds > LED_ALL)
Simon Glasse53cc1d2015-01-08 05:48:51 -0700294 leds = LED_ALL;
stepan4c06de72011-01-28 09:00:15 +0000295
David Hendricks14e82e52015-08-15 17:59:03 -0700296 /* Older Dediprogs with 2.x.x and 3.x.x firmware only had two LEDs, assigned to different bits. So map
297 * them around if we have an old device. On those devices the LEDs map as follows:
stepan4c06de72011-01-28 09:00:15 +0000298 * bit 2 == 0: green light is on.
David Hendricks14e82e52015-08-15 17:59:03 -0700299 * bit 0 == 0: red light is on.
300 *
301 * Additionally, the command structure has changed with the "new" protocol.
302 *
303 * FIXME: take IO pins into account
stepan4c06de72011-01-28 09:00:15 +0000304 */
David Hendricks14e82e52015-08-15 17:59:03 -0700305 int target_leds, ret;
306 if (is_new_prot()) {
307 target_leds = (leds ^ 7) << 8;
David Hendricksa7f99ac2015-11-12 16:42:03 -0800308 ret = dediprog_write_ep(CMD_SET_IO_LED, target_leds, 0, NULL, 0);
stepan4c06de72011-01-28 09:00:15 +0000309 } else {
David Hendricks14e82e52015-08-15 17:59:03 -0700310 if (dediprog_firmwareversion < FIRMWARE_VERSION(5, 0, 0)) {
311 target_leds = ((leds & LED_ERROR) >> 2) | ((leds & LED_PASS) << 2);
312 } else {
313 target_leds = leds;
314 }
315 target_leds ^= 7;
316
David Hendricksa7f99ac2015-11-12 16:42:03 -0800317 ret = dediprog_write_ep(CMD_SET_IO_LED, 0x9, target_leds, NULL, 0);
Simon Glass543101a2015-01-08 06:28:13 -0700318 }
David Hendricksfe05e742015-08-15 17:29:39 -0700319
stepan4c06de72011-01-28 09:00:15 +0000320 if (ret != 0x0) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800321 msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, libusb_error_name(ret));
stepan4c06de72011-01-28 09:00:15 +0000322 return 1;
323 }
324
stepan4c06de72011-01-28 09:00:15 +0000325 return 0;
326}
327
David Hendricksfe05e742015-08-15 17:29:39 -0700328struct dediprog_spispeeds {
329 const char *const name;
330 const int speed;
331};
332
333static const struct dediprog_spispeeds spispeeds[] = {
334 { "24M", 0x0 },
335 { "12M", 0x2 },
336 { "8M", 0x1 },
337 { "3M", 0x3 },
338 { "2.18M", 0x4 },
339 { "1.5M", 0x5 },
340 { "750k", 0x6 },
341 { "375k", 0x7 },
342 { NULL, 0x0 },
343};
344
345static int dediprog_set_spi_speed(unsigned int spispeed_idx)
hailfingerdfb32a02010-01-19 11:15:48 +0000346{
David Hendricksfe05e742015-08-15 17:29:39 -0700347 if (dediprog_firmwareversion < FIRMWARE_VERSION(5, 0, 0)) {
348 msg_pinfo("Skipping to set SPI speed because firmware is too old.\n");
349 return 0;
350 }
hailfingerdfb32a02010-01-19 11:15:48 +0000351
David Hendricksfe05e742015-08-15 17:29:39 -0700352 const struct dediprog_spispeeds *spispeed = &spispeeds[spispeed_idx];
353 msg_pdbg("SPI speed is %sHz\n", spispeed->name);
hailfingerdfb32a02010-01-19 11:15:48 +0000354
David Hendricksa7f99ac2015-11-12 16:42:03 -0800355 int ret = dediprog_write_ep(CMD_SET_SPI_CLK, spispeed->speed, 0, NULL, 0);
hailfingerdfb32a02010-01-19 11:15:48 +0000356 if (ret != 0x0) {
David Hendricksfe05e742015-08-15 17:29:39 -0700357 msg_perr("Command Set SPI Speed 0x%x failed!\n", spispeed->speed);
hailfingerdfb32a02010-01-19 11:15:48 +0000358 return 1;
359 }
360 return 0;
361}
362
hailfingerfb6287d2010-11-16 21:25:29 +0000363/* Bulk read interface, will read multiple 512 byte chunks aligned to 512 bytes.
364 * @start start address
365 * @len length
366 * @return 0 on success, 1 on failure
367 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700368static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf,
stefanctc5eb8a92011-11-23 09:13:48 +0000369 unsigned int start, unsigned int len)
hailfingerfb6287d2010-11-16 21:25:29 +0000370{
David Hendricksf9ecb452015-11-04 15:40:27 -0800371 int ret, err = 1;
stefanctc5eb8a92011-11-23 09:13:48 +0000372 unsigned int i;
hailfingerfb6287d2010-11-16 21:25:29 +0000373 /* chunksize must be 512, other sizes will NOT work at all. */
stefanctc5eb8a92011-11-23 09:13:48 +0000374 const unsigned int chunksize = 0x200;
375 const unsigned int count = len / chunksize;
David Hendricks14e82e52015-08-15 17:59:03 -0700376 unsigned int cmd_len;
David Hendricksf9ecb452015-11-04 15:40:27 -0800377 struct dediprog_transfer_status status = { 0, 0, 0 };
378 struct libusb_transfer *transfers[DEDIPROG_ASYNC_TRANSFERS] = { NULL, };
379 struct libusb_transfer *transfer;
hailfingerfb6287d2010-11-16 21:25:29 +0000380
381 if ((start % chunksize) || (len % chunksize)) {
382 msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
383 "at flashrom@flashrom.org\n", __func__, start, len);
384 return 1;
385 }
386
387 /* No idea if the hardware can handle empty reads, so chicken out. */
388 if (!len)
389 return 0;
David Hendricks14e82e52015-08-15 17:59:03 -0700390 /* Command Read SPI Bulk. */
391 if (is_new_prot()) {
392 const uint8_t read_cmd[] = {
393 count & 0xff,
394 (count >> 8) & 0xff,
395 0,
396 READ_MODE_FAST,
397 0,
398 0,
399 start & 0xff,
400 (start >> 8) & 0xff,
401 (start >> 16) & 0xff,
402 (start >> 24) & 0xff,
403 };
404
405 cmd_len = sizeof(read_cmd);
David Hendricksa7f99ac2015-11-12 16:42:03 -0800406 ret = dediprog_write_ep(CMD_READ, 0, 0, read_cmd, cmd_len);
David Hendricks14e82e52015-08-15 17:59:03 -0700407 } else {
408 const uint8_t read_cmd[] = {count & 0xff,
409 (count >> 8) & 0xff,
410 chunksize & 0xff,
411 (chunksize >> 8) & 0xff};
412
413 cmd_len = sizeof(read_cmd);
David Hendricksa7f99ac2015-11-12 16:42:03 -0800414 ret = dediprog_write_ep(CMD_READ, start % 0x10000, start / 0x10000, read_cmd, cmd_len);
David Hendricks14e82e52015-08-15 17:59:03 -0700415 }
416 if (ret != cmd_len) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800417 msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, libusb_error_name(ret));
hailfingerfb6287d2010-11-16 21:25:29 +0000418 return 1;
419 }
420
David Hendricksf9ecb452015-11-04 15:40:27 -0800421 /*
422 * Ring buffer of bulk transfers.
423 * Poll until at least one transfer is ready,
424 * schedule next transfers until buffer is full.
425 */
hailfingerfb6287d2010-11-16 21:25:29 +0000426
David Hendricksf9ecb452015-11-04 15:40:27 -0800427 /* Allocate bulk transfers. */
428 for (i = 0; i < min(DEDIPROG_ASYNC_TRANSFERS, count); ++i) {
429 transfers[i] = libusb_alloc_transfer(0);
430 if (!transfers[i]) {
431 msg_perr("Allocating libusb transfer %i failed: %s!\n", i, libusb_error_name(ret));
432 goto _err_free;
433 }
434 }
435
436 /* Now transfer requested chunks using libusb's asynchronous interface. */
437 while (!status.error && (status.queued_idx < count)) {
438 while ((status.queued_idx - status.finished_idx) < DEDIPROG_ASYNC_TRANSFERS) {
439 transfer = transfers[status.queued_idx % DEDIPROG_ASYNC_TRANSFERS];
440 libusb_fill_bulk_transfer(transfer, dediprog_handle, 0x80 | dediprog_in_endpoint,
441 (unsigned char *)buf + status.queued_idx * chunksize, chunksize,
442 dediprog_bulk_read_cb, &status, DEFAULT_TIMEOUT);
443 transfer->flags |= LIBUSB_TRANSFER_SHORT_NOT_OK;
444 ret = libusb_submit_transfer(transfer);
445 if (ret < 0) {
446 msg_perr("Submitting SPI bulk read %i failed: %i %s!\n",
447 status.queued_idx, ret, libusb_error_name(ret));
448 goto _err_free;
449 }
450 ++status.queued_idx;
451 }
452 if (dediprog_bulk_read_poll(&status, 0))
453 goto _err_free;
454 }
455 /* Wait for transfers to finish. */
456 if (dediprog_bulk_read_poll(&status, 1))
457 goto _err_free;
458 /* Check if everything has been transmitted. */
459 if ((status.finished_idx < count) || status.error)
460 goto _err_free;
461
462 err = 0;
463
464_err_free:
465 dediprog_bulk_read_poll(&status, 1);
466 for (i = 0; i < DEDIPROG_ASYNC_TRANSFERS; ++i)
467 if (transfers[i]) libusb_free_transfer(transfers[i]);
468 return err;
hailfingerfb6287d2010-11-16 21:25:29 +0000469}
470
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700471static int dediprog_spi_read(struct flashctx *flash, uint8_t *buf,
stefanctc5eb8a92011-11-23 09:13:48 +0000472 unsigned int start, unsigned int len)
hailfingerdfb32a02010-01-19 11:15:48 +0000473{
hailfingerfb6287d2010-11-16 21:25:29 +0000474 int ret;
475 /* chunksize must be 512, other sizes will NOT work at all. */
stefanctc5eb8a92011-11-23 09:13:48 +0000476 const unsigned int chunksize = 0x200;
477 unsigned int residue = start % chunksize ? chunksize - start % chunksize : 0;
478 unsigned int bulklen;
hailfingerfb6287d2010-11-16 21:25:29 +0000479
Simon Glasse53cc1d2015-01-08 05:48:51 -0700480 dediprog_set_leds(LED_BUSY);
stepan4c06de72011-01-28 09:00:15 +0000481
hailfingerfb6287d2010-11-16 21:25:29 +0000482 if (residue) {
483 msg_pdbg("Slow read for partial block from 0x%x, length 0x%x\n",
484 start, residue);
485 ret = spi_read_chunked(flash, buf, start, residue, 16);
Simon Glasse53cc1d2015-01-08 05:48:51 -0700486 if (ret)
487 goto err;
hailfingerfb6287d2010-11-16 21:25:29 +0000488 }
489
490 /* Round down. */
491 bulklen = (len - residue) / chunksize * chunksize;
492 ret = dediprog_spi_bulk_read(flash, buf + residue, start + residue,
493 bulklen);
Simon Glasse53cc1d2015-01-08 05:48:51 -0700494 if (ret)
495 goto err;
hailfingerfb6287d2010-11-16 21:25:29 +0000496
497 len -= residue + bulklen;
498 if (len) {
499 msg_pdbg("Slow read for partial block from 0x%x, length 0x%x\n",
500 start, len);
501 ret = spi_read_chunked(flash, buf + residue + bulklen,
502 start + residue + bulklen, len, 16);
Simon Glasse53cc1d2015-01-08 05:48:51 -0700503 if (ret)
504 goto err;
hailfingerfb6287d2010-11-16 21:25:29 +0000505 }
506
Simon Glasse53cc1d2015-01-08 05:48:51 -0700507 dediprog_set_leds(LED_PASS);
hailfingerfb6287d2010-11-16 21:25:29 +0000508 return 0;
Simon Glasse53cc1d2015-01-08 05:48:51 -0700509err:
510 dediprog_set_leds(LED_ERROR);
511 return ret;
hailfingerdfb32a02010-01-19 11:15:48 +0000512}
513
David Hendricksfe05e742015-08-15 17:29:39 -0700514/* Bulk write interface, will write multiple chunksize byte chunks aligned to chunksize bytes.
515 * @chunksize length of data chunks, only 256 supported by now
516 * @start start address
517 * @len length
518 * @dedi_spi_cmd dediprog specific write command for spi bus
519 * @return 0 on success, 1 on failure
520 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700521static int dediprog_spi_bulk_write(struct flashctx *flash, const uint8_t *buf, unsigned int chunksize,
David Hendricksfe05e742015-08-15 17:29:39 -0700522 unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
hailfinger556e9c32010-11-23 21:28:16 +0000523{
David Hendricksf9ecb452015-11-04 15:40:27 -0800524 int ret, transferred;
David Hendricksfe05e742015-08-15 17:29:39 -0700525 unsigned int i;
526 /* USB transfer size must be 512, other sizes will NOT work at all.
527 * chunksize is the real data size per USB bulk transfer. The remaining
528 * space in a USB bulk transfer must be filled with 0xff padding.
529 */
530 const unsigned int count = len / chunksize;
David Hendricksf9ecb452015-11-04 15:40:27 -0800531 const unsigned char count_and_cmd_old[] = {count & 0xff, (count >> 8) & 0xff, 0x00, dedi_spi_cmd};
532 const unsigned char count_and_cmd_new[] = {
David Hendricks741efe22015-08-15 19:18:51 -0700533 count & 0xff,
534 (count >> 8) & 0xff,
535 0, /* used for 24-bit address support? */
536 dedi_spi_cmd,
537 JEDEC_BYTE_PROGRAM, /* FIXME: needs to be determined based on byte 3? */
538 0,
539 start & 0xff,
540 (start >> 8) & 0xff,
541 (start >> 16) & 0xff,
542 (start >> 24) & 0xff,
543 };
David Hendricksf9ecb452015-11-04 15:40:27 -0800544 unsigned char usbbuf[512];
David Hendricksfe05e742015-08-15 17:29:39 -0700545
546 /*
547 * We should change this check to
548 * chunksize > 512
549 * once we know how to handle different chunk sizes.
550 */
551 if (chunksize != 256) {
552 msg_perr("%s: Chunk sizes other than 256 bytes are unsupported, chunksize=%u!\n"
553 "Please report a bug at flashrom@flashrom.org\n", __func__, chunksize);
554 return 1;
555 }
556
557 if ((start % chunksize) || (len % chunksize)) {
558 msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
559 "at flashrom@flashrom.org\n", __func__, start, len);
560 return 1;
561 }
562
563 /* No idea if the hardware can handle empty writes, so chicken out. */
564 if (!len)
565 return 0;
David Hendricks741efe22015-08-15 19:18:51 -0700566 if (!is_new_prot()) {
567 /* Command Write SPI Bulk. No idea which write command is used on the
568 * SPI side.
569 */
David Hendricksa7f99ac2015-11-12 16:42:03 -0800570 ret = dediprog_write_ep(CMD_WRITE, start % 0x10000, start / 0x10000,
David Hendricksf9ecb452015-11-04 15:40:27 -0800571 count_and_cmd_old, sizeof(count_and_cmd_old));
David Hendricks741efe22015-08-15 19:18:51 -0700572 if (ret != sizeof(count_and_cmd_old)) {
573 msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret,
David Hendricksf9ecb452015-11-04 15:40:27 -0800574 libusb_error_name(ret));
David Hendricks741efe22015-08-15 19:18:51 -0700575 return 1;
576 }
577 } else {
578 /* Command Write SPI Bulk. No idea which write command is used on the
579 * SPI side.
580 */
David Hendricksa7f99ac2015-11-12 16:42:03 -0800581 ret = dediprog_write_ep(CMD_WRITE, 0, 0,
David Hendricksf9ecb452015-11-04 15:40:27 -0800582 count_and_cmd_new, sizeof(count_and_cmd_new));
David Hendricks741efe22015-08-15 19:18:51 -0700583 if (ret != sizeof(count_and_cmd_new)) {
584 msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret,
David Hendricksf9ecb452015-11-04 15:40:27 -0800585 libusb_error_name(ret));
David Hendricks741efe22015-08-15 19:18:51 -0700586 return 1;
587 }
David Hendricksfe05e742015-08-15 17:29:39 -0700588 }
589
590 for (i = 0; i < count; i++) {
591 memset(usbbuf, 0xff, sizeof(usbbuf));
592 memcpy(usbbuf, buf + i * chunksize, chunksize);
David Hendricksf9ecb452015-11-04 15:40:27 -0800593 ret = libusb_bulk_transfer(dediprog_handle, dediprog_out_endpoint,
594 usbbuf, 512, &transferred, DEFAULT_TIMEOUT);
595 if ((ret < 0) || (transferred != 512)) {
596 msg_perr("SPI bulk write failed, expected %i, got %i %s!\n",
597 512, ret, libusb_error_name(ret));
David Hendricksfe05e742015-08-15 17:29:39 -0700598 return 1;
599 }
600 }
601
602 return 0;
603}
604
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700605static int dediprog_spi_write(struct flashctx *flash, const uint8_t *buf,
David Hendricksfe05e742015-08-15 17:29:39 -0700606 unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
607{
608 int ret;
David Hendricksfe05e742015-08-15 17:29:39 -0700609 const unsigned int chunksize = flash->page_size;
610 unsigned int residue = start % chunksize ? chunksize - start % chunksize : 0;
611 unsigned int bulklen;
stepan4c06de72011-01-28 09:00:15 +0000612
Simon Glasse53cc1d2015-01-08 05:48:51 -0700613 dediprog_set_leds(LED_BUSY);
stepan4c06de72011-01-28 09:00:15 +0000614
David Hendricksfe05e742015-08-15 17:29:39 -0700615 if (chunksize != 256) {
616 msg_pdbg("Page sizes other than 256 bytes are unsupported as "
617 "we don't know how dediprog\nhandles them.\n");
618 /* Write everything like it was residue. */
619 residue = len;
620 }
stepan4c06de72011-01-28 09:00:15 +0000621
David Hendricksfe05e742015-08-15 17:29:39 -0700622 if (residue) {
623 msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
624 start, residue);
625 /* No idea about the real limit. Maybe 12, maybe more. */
626 ret = spi_write_chunked(flash, (uint8_t *)buf, start, residue, 12);
627 if (ret) {
628 dediprog_set_leds(LED_ERROR);
629 return ret;
630 }
631 }
632
633 /* Round down. */
634 bulklen = (len - residue) / chunksize * chunksize;
635 ret = dediprog_spi_bulk_write(flash, buf + residue, chunksize, start + residue, bulklen, dedi_spi_cmd);
636 if (ret) {
Simon Glasse53cc1d2015-01-08 05:48:51 -0700637 dediprog_set_leds(LED_ERROR);
David Hendricksfe05e742015-08-15 17:29:39 -0700638 return ret;
639 }
stepan4c06de72011-01-28 09:00:15 +0000640
David Hendricksfe05e742015-08-15 17:29:39 -0700641 len -= residue + bulklen;
642 if (len) {
643 msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
644 start, len);
645 ret = spi_write_chunked(flash, (uint8_t *)(buf + residue + bulklen),
646 start + residue + bulklen, len, 12);
647 if (ret) {
648 dediprog_set_leds(LED_ERROR);
649 return ret;
650 }
651 }
652
653 dediprog_set_leds(LED_PASS);
654 return 0;
hailfinger556e9c32010-11-23 21:28:16 +0000655}
656
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700657//static int dediprog_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
658static int dediprog_spi_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
David Hendricksfe05e742015-08-15 17:29:39 -0700659{
660 return dediprog_spi_write(flash, buf, start, len, WRITE_MODE_PAGE_PGM);
661}
662
663#if 0
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700664static 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 -0700665{
666 return dediprog_spi_write(flash, buf, start, len, WRITE_MODE_2B_AAI);
667}
668#endif
669
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700670//static int dediprog_spi_send_command(struct flashctx *flash,
671static int dediprog_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
David Hendricksfe05e742015-08-15 17:29:39 -0700672 unsigned int readcnt,
673 const unsigned char *writearr,
674 unsigned char *readarr)
hailfingerdfb32a02010-01-19 11:15:48 +0000675{
676 int ret;
677
hailfingeraf389cc2010-01-22 02:53:30 +0000678 msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
David Hendricksfe05e742015-08-15 17:29:39 -0700679 if (writecnt > UINT16_MAX) {
680 msg_perr("Invalid writecnt=%i, aborting.\n", writecnt);
681 return 1;
Simon Glass543101a2015-01-08 06:28:13 -0700682 }
David Hendricksfe05e742015-08-15 17:29:39 -0700683 if (readcnt > UINT16_MAX) {
684 msg_perr("Invalid readcnt=%i, aborting.\n", readcnt);
685 return 1;
686 }
687
David Hendricks14e82e52015-08-15 17:59:03 -0700688 /* New protocol has the read flag as value while the old protocol had it in the index field. */
689 if (is_new_prot()) {
David Hendricksa7f99ac2015-11-12 16:42:03 -0800690 ret = dediprog_write_ep(CMD_TRANSCEIVE, readcnt ? 1 : 0, 0, writearr, writecnt);
David Hendricks14e82e52015-08-15 17:59:03 -0700691 } else {
David Hendricksa7f99ac2015-11-12 16:42:03 -0800692 ret = dediprog_write_ep(CMD_TRANSCEIVE, 0, readcnt ? 1 : 0, writearr, writecnt);
David Hendricks14e82e52015-08-15 17:59:03 -0700693 }
hailfingerdfb32a02010-01-19 11:15:48 +0000694 if (ret != writecnt) {
hailfingeraf389cc2010-01-22 02:53:30 +0000695 msg_perr("Send SPI failed, expected %i, got %i %s!\n",
David Hendricksf9ecb452015-11-04 15:40:27 -0800696 writecnt, ret, libusb_error_name(ret));
hailfingerdfb32a02010-01-19 11:15:48 +0000697 return 1;
698 }
David Hendricksfe05e742015-08-15 17:29:39 -0700699 if (readcnt == 0)
hailfingerdfb32a02010-01-19 11:15:48 +0000700 return 0;
David Hendricksfe05e742015-08-15 17:29:39 -0700701
David Hendricksa7f99ac2015-11-12 16:42:03 -0800702 ret = dediprog_read_ep(CMD_TRANSCEIVE, 0, 0, readarr, readcnt);
hailfingerdfb32a02010-01-19 11:15:48 +0000703 if (ret != readcnt) {
hailfingeraf389cc2010-01-22 02:53:30 +0000704 msg_perr("Receive SPI failed, expected %i, got %i %s!\n",
David Hendricksf9ecb452015-11-04 15:40:27 -0800705 readcnt, ret, libusb_error_name(ret));
hailfingerdfb32a02010-01-19 11:15:48 +0000706 return 1;
707 }
708 return 0;
709}
710
hailfinger1ff33dc2010-07-03 11:02:10 +0000711static int dediprog_check_devicestring(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000712{
713 int ret;
hailfinger7a009082010-11-09 23:30:43 +0000714 int fw[3];
David Hendricks6702e072015-08-15 18:09:04 -0700715 int sfnum;
hailfingerdfb32a02010-01-19 11:15:48 +0000716 char buf[0x11];
717
hailfingerdfb32a02010-01-19 11:15:48 +0000718 /* Command Receive Device String. */
David Hendricksa7f99ac2015-11-12 16:42:03 -0800719 ret = dediprog_read_ep(CMD_READ_PROG_INFO, 0, 0, (uint8_t *)buf, 0x10);
hailfingerdfb32a02010-01-19 11:15:48 +0000720 if (ret != 0x10) {
721 msg_perr("Incomplete/failed Command Receive Device String!\n");
722 return 1;
723 }
724 buf[0x10] = '\0';
725 msg_pdbg("Found a %s\n", buf);
David Hendricks6702e072015-08-15 18:09:04 -0700726 if (memcmp(buf, "SF100", 0x5) == 0)
727 dediprog_devicetype = DEV_SF100;
728 else if (memcmp(buf, "SF600", 0x5) == 0)
729 dediprog_devicetype = DEV_SF600;
730 else {
David Hendricks22593802015-11-13 12:59:30 -0800731 msg_perr("Device not a SF100 or SF600!\n");
hailfingerdfb32a02010-01-19 11:15:48 +0000732 return 1;
733 }
David Hendricks6702e072015-08-15 18:09:04 -0700734 if (sscanf(buf, "SF%d V:%d.%d.%d ", &sfnum, &fw[0], &fw[1], &fw[2])
735 != 4 || sfnum != dediprog_devicetype) {
David Hendricks14e82e52015-08-15 17:59:03 -0700736 msg_perr("Unexpected firmware version string '%s'\n", buf);
hailfinger7a009082010-11-09 23:30:43 +0000737 return 1;
738 }
David Hendricks14e82e52015-08-15 17:59:03 -0700739 /* Only these major versions were tested. */
David Hendricks6702e072015-08-15 18:09:04 -0700740 if (fw[0] < 2 || fw[0] > 7) {
David Hendricks14e82e52015-08-15 17:59:03 -0700741 msg_perr("Unexpected firmware version %d.%d.%d!\n", fw[0], fw[1], fw[2]);
hailfingerdfb32a02010-01-19 11:15:48 +0000742 return 1;
743 }
stepan4c06de72011-01-28 09:00:15 +0000744 dediprog_firmwareversion = FIRMWARE_VERSION(fw[0], fw[1], fw[2]);
David Hendricks14e82e52015-08-15 17:59:03 -0700745
hailfingerdfb32a02010-01-19 11:15:48 +0000746 return 0;
747}
748
David Hendricks91ca7ac2015-11-20 16:22:22 -0800749static int dediprog_supply_voltages[] = {
750 0, 1800, 2500, 3500,
751};
752
753static int dediprog_set_spi_flash_voltage_manual(int millivolt)
754{
755 int ret;
756 uint16_t voltage_selector;
757
758 switch (millivolt) {
759 case 0:
760 /* Admittedly this one is an assumption. */
761 voltage_selector = 0x0;
762 break;
763 case 1800:
764 voltage_selector = 0x12;
765 break;
766 case 2500:
767 voltage_selector = 0x11;
768 break;
769 case 3500:
770 voltage_selector = 0x10;
771 break;
772 default:
773 msg_perr("Unknown voltage %i mV! Aborting.\n", millivolt);
774 return 1;
775 }
776 msg_pdbg("Setting SPI voltage to %u.%03u V\n", millivolt / 1000,
777 millivolt % 1000);
778
779 if (voltage_selector == 0) {
780 /* Wait some time as the original driver does. */
781 programmer_delay(200 * 1000);
782 }
783 ret = dediprog_write_ep(CMD_SET_VCC, voltage_selector, 0, NULL, 0);
784 if (ret != 0x0) {
785 msg_perr("Command Set SPI Voltage 0x%x failed!\n",
786 voltage_selector);
787 return 1;
788 }
789 if (voltage_selector != 0) {
790 /* Wait some time as the original driver does. */
791 programmer_delay(200 * 1000);
792 }
793 return 0;
794}
795
David Hendricks93784b42016-08-09 17:00:38 -0700796static int dediprog_set_spi_flash_voltage_auto(void)
David Hendricks91ca7ac2015-11-20 16:22:22 -0800797{
Souvik Ghosh63b92f92016-06-29 18:45:52 -0700798 int i, k;
David Hendricks91ca7ac2015-11-20 16:22:22 -0800799 int spi_flash_ranges;
David Hendricks93784b42016-08-09 17:00:38 -0700800 struct registered_programmer *pgm;
David Hendricks91ca7ac2015-11-20 16:22:22 -0800801
802 spi_flash_ranges = flash_supported_voltage_ranges(BUS_SPI);
803 if (spi_flash_ranges < 0)
804 return -1;
805
David Hendricks93784b42016-08-09 17:00:38 -0700806 /* FIXME: This first for loop might be logically incorrect (and even if it's not, it's
807 quite hacky and inefficient). Might be able to bypass this by passing in
808 an argument to this function */
809 for (k = 0; k < registered_programmer_count; k++){
810 pgm = &registered_programmers[k];
811 if(pgm->spi.type == SPI_CONTROLLER_DEDIPROG){
812 break;
813 }
814 }
Souvik Ghosh63b92f92016-06-29 18:45:52 -0700815 if( k == registered_programmer_count )
816 return 1; /* we couldn't find the dediprog registered controller so we're
817 exiting with an error */
818
David Hendricks91ca7ac2015-11-20 16:22:22 -0800819 for (i = 0; i < ARRAY_SIZE(dediprog_supply_voltages); i++) {
820 int j;
821 int v = dediprog_supply_voltages[i]; /* shorthand */
822
823 for (j = 0; j < spi_flash_ranges; j++) {
824 /* Dediprog can supply a voltage in this range. */
825 if ((v >= voltage_ranges[j].min) && (v <= voltage_ranges[j].max)) {
David Hendricks93784b42016-08-09 17:00:38 -0700826 struct flashctx dummy;
827
David Hendricks91ca7ac2015-11-20 16:22:22 -0800828 msg_cdbg("%s: trying %d\n", __func__, v);
829 if (dediprog_set_spi_flash_voltage_manual(v)) {
830 msg_cerr("%s: Failed to set SPI voltage\n", __func__);
831 return 1;
832 }
833
834 clear_spi_id_cache();
David Hendricks93784b42016-08-09 17:00:38 -0700835 if (probe_flash(pgm, 0, &dummy, 0) < 0) {
David Hendricks91ca7ac2015-11-20 16:22:22 -0800836 /* No dice, try next voltage supported by Dediprog. */
837 break;
838 }
839
David Hendricks93784b42016-08-09 17:00:38 -0700840 if ((dummy.manufacture_id == GENERIC_MANUF_ID) ||
841 (dummy.model_id == GENERIC_DEVICE_ID)) {
David Hendricks91ca7ac2015-11-20 16:22:22 -0800842 break;
843 }
844
845 return 0;
846 }
847 }
848 }
849
850 return 1;
851}
852
853/* FIXME: ugly function signature */
David Hendricks93784b42016-08-09 17:00:38 -0700854static int dediprog_set_spi_voltage(int millivolt, int probe)
David Hendricks91ca7ac2015-11-20 16:22:22 -0800855{
856 if (probe)
David Hendricks93784b42016-08-09 17:00:38 -0700857 return dediprog_set_spi_flash_voltage_auto();
David Hendricks91ca7ac2015-11-20 16:22:22 -0800858 else
859 return dediprog_set_spi_flash_voltage_manual(millivolt);
860}
861
David Hendricks28fbdfb2015-08-15 18:04:37 -0700862/*
863 * This command presumably sets the voltage for the SF100 itself (not the
864 * SPI flash). Only use this command with firmware older than V6.0.0. Newer
865 * (including all SF600s) do not support it.
866 */
867static int dediprog_set_voltage(void)
hailfingerdfb32a02010-01-19 11:15:48 +0000868{
869 int ret;
David Hendricksf9ecb452015-11-04 15:40:27 -0800870 unsigned char buf[0x1];
hailfingerdfb32a02010-01-19 11:15:48 +0000871
872 memset(buf, 0, sizeof(buf));
David Hendricksa7f99ac2015-11-12 16:42:03 -0800873 ret = dediprog_read_other(CMD_SET_VOLTAGE, 0x0, 0x0, buf, 0x1);
hailfinger7a009082010-11-09 23:30:43 +0000874 if (ret < 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800875 msg_perr("Command A failed (%s)!\n", libusb_error_name(ret));
hailfinger7a009082010-11-09 23:30:43 +0000876 return 1;
877 }
hailfingerdfb32a02010-01-19 11:15:48 +0000878 if ((ret != 0x1) || (buf[0] != 0x6f)) {
Simon Glassa1f80682015-01-08 05:55:29 -0700879 msg_perr("Unexpected response to init!\n");
hailfingerdfb32a02010-01-19 11:15:48 +0000880 return 1;
881 }
882 return 0;
883}
884
David Hendrickscf453d82015-11-16 20:19:57 -0800885static int dediprog_leave_standalone_mode(void)
886{
887 int ret;
888
889 if (dediprog_devicetype != DEV_SF600)
890 return 0;
891
892 msg_pdbg("Leaving standalone mode\n");
893 ret = dediprog_write_ep(CMD_SET_STANDALONE, LEAVE_STANDALONE_MODE, 0, NULL, 0);
894 if (ret) {
895 msg_perr("Failed to leave standalone mode (%s)!\n", libusb_error_name(ret));
896 return 1;
897 }
898
899 return 0;
900}
901
David Hendricksfe05e742015-08-15 17:29:39 -0700902static int set_target_flash(enum dediprog_target target)
903{
David Hendricksa7f99ac2015-11-12 16:42:03 -0800904 int ret = dediprog_write_ep(CMD_SET_TARGET, target, 0, NULL, 0);
David Hendricksfe05e742015-08-15 17:29:39 -0700905 if (ret != 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -0800906 msg_perr("set_target_flash failed (%s)!\n", libusb_error_name(ret));
hailfingerdfb32a02010-01-19 11:15:48 +0000907 return 1;
908 }
909 return 0;
910}
911
David Hendricksfe05e742015-08-15 17:29:39 -0700912#if 0
913/* Returns true if the button is currently pressed. */
914static bool dediprog_get_button(void)
Simon Glassd01002b2015-01-08 05:44:16 -0700915{
David Hendricksfe05e742015-08-15 17:29:39 -0700916 char buf[1];
917 int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_GET_BUTTON, 0, 0,
918 buf, 0x1, DEFAULT_TIMEOUT);
919 if (ret != 0) {
920 msg_perr("Could not get button state (%s)!\n", usb_strerror());
921 return 1;
Simon Glassd01002b2015-01-08 05:44:16 -0700922 }
David Hendricksfe05e742015-08-15 17:29:39 -0700923 return buf[0] != 1;
Simon Glassd01002b2015-01-08 05:44:16 -0700924}
David Hendricksfe05e742015-08-15 17:29:39 -0700925#endif
Simon Glassd01002b2015-01-08 05:44:16 -0700926
hailfingerf76cc322010-11-09 22:00:31 +0000927static int parse_voltage(char *voltage)
928{
929 char *tmp = NULL;
hailfingerb91c08c2011-08-15 19:54:20 +0000930 int i;
931 int millivolt = 0, fraction = 0;
hailfingerf76cc322010-11-09 22:00:31 +0000932
933 if (!voltage || !strlen(voltage)) {
934 msg_perr("Empty voltage= specified.\n");
935 return -1;
936 }
937 millivolt = (int)strtol(voltage, &tmp, 0);
938 voltage = tmp;
939 /* Handle "," and "." as decimal point. Everything after it is assumed
940 * to be in decimal notation.
941 */
942 if ((*voltage == '.') || (*voltage == ',')) {
943 voltage++;
944 for (i = 0; i < 3; i++) {
945 fraction *= 10;
946 /* Don't advance if the current character is invalid,
947 * but continue multiplying.
948 */
949 if ((*voltage < '0') || (*voltage > '9'))
950 continue;
951 fraction += *voltage - '0';
952 voltage++;
953 }
954 /* Throw away remaining digits. */
955 voltage += strspn(voltage, "0123456789");
956 }
957 /* The remaining string must be empty or "mV" or "V". */
958 tolower_string(voltage);
959
960 /* No unit or "V". */
961 if ((*voltage == '\0') || !strncmp(voltage, "v", 1)) {
962 millivolt *= 1000;
963 millivolt += fraction;
964 } else if (!strncmp(voltage, "mv", 2) ||
965 !strncmp(voltage, "milliv", 6)) {
966 /* No adjustment. fraction is discarded. */
967 } else {
968 /* Garbage at the end of the string. */
969 msg_perr("Garbage voltage= specified.\n");
970 return -1;
971 }
972 return millivolt;
973}
974
David Hendricksfe05e742015-08-15 17:29:39 -0700975#if 0
976static const struct spi_master spi_master_dediprog = {
977 .type = SPI_CONTROLLER_DEDIPROG,
978 .max_data_read = MAX_DATA_UNSPECIFIED,
979 .max_data_write = MAX_DATA_UNSPECIFIED,
980 .command = dediprog_spi_send_command,
981 .multicommand = default_spi_send_multicommand,
982 .read = dediprog_spi_read,
983 .write_256 = dediprog_spi_write_256,
984 .write_aai = dediprog_spi_write_aai,
985};
986#endif
mkarcherd264e9e2011-05-11 17:07:07 +0000987static const struct spi_programmer spi_programmer_dediprog = {
uwe8d342eb2011-07-28 08:13:25 +0000988 .type = SPI_CONTROLLER_DEDIPROG,
989 .max_data_read = MAX_DATA_UNSPECIFIED,
990 .max_data_write = MAX_DATA_UNSPECIFIED,
991 .command = dediprog_spi_send_command,
992 .multicommand = default_spi_send_multicommand,
993 .read = dediprog_spi_read,
994 .write_256 = dediprog_spi_write_256,
mkarcherd264e9e2011-05-11 17:07:07 +0000995};
996
David Hendricks93784b42016-08-09 17:00:38 -0700997static int dediprog_shutdown(void *data)
dhendrix0ffc2eb2011-06-14 01:35:36 +0000998{
999 msg_pspew("%s\n", __func__);
1000
David Hendricksfe05e742015-08-15 17:29:39 -07001001 dediprog_firmwareversion = FIRMWARE_VERSION(0, 0, 0);
David Hendricks6702e072015-08-15 18:09:04 -07001002 dediprog_devicetype = DEV_UNKNOWN;
David Hendricksfe05e742015-08-15 17:29:39 -07001003
dhendrix0ffc2eb2011-06-14 01:35:36 +00001004 /* URB 28. Command Set SPI Voltage to 0. */
David Hendricks93784b42016-08-09 17:00:38 -07001005 if (dediprog_set_spi_voltage(0x0, 0))
dhendrix0ffc2eb2011-06-14 01:35:36 +00001006 return 1;
1007
David Hendricksf9ecb452015-11-04 15:40:27 -08001008 if (libusb_release_interface(dediprog_handle, 0)) {
dhendrix0ffc2eb2011-06-14 01:35:36 +00001009 msg_perr("Could not release USB interface!\n");
1010 return 1;
1011 }
David Hendricksf9ecb452015-11-04 15:40:27 -08001012 libusb_close(dediprog_handle);
1013 libusb_exit(usb_ctx);
1014
dhendrix0ffc2eb2011-06-14 01:35:36 +00001015 return 0;
1016}
1017
hailfingerdfb32a02010-01-19 11:15:48 +00001018/* URB numbers refer to the first log ever captured. */
Souvik Ghosh63b92f92016-06-29 18:45:52 -07001019int dediprog_init(struct flashctx *flash)
hailfingerdfb32a02010-01-19 11:15:48 +00001020{
David Hendricksfe05e742015-08-15 17:29:39 -07001021 char *voltage, *device, *spispeed, *target_str;
1022 int spispeed_idx = 1;
David Hendrickscd20ea42015-11-17 22:33:35 -08001023 int millivolt = 0;
David Hendricksfe05e742015-08-15 17:29:39 -07001024 long usedevice = 0;
1025 long target = 1;
1026 int i, ret;
hailfingerdfb32a02010-01-19 11:15:48 +00001027
1028 msg_pspew("%s\n", __func__);
1029
David Hendricksfe05e742015-08-15 17:29:39 -07001030 spispeed = extract_programmer_param("spispeed");
1031 if (spispeed) {
1032 for (i = 0; spispeeds[i].name; ++i) {
1033 if (!strcasecmp(spispeeds[i].name, spispeed)) {
1034 spispeed_idx = i;
1035 break;
1036 }
1037 }
1038 if (!spispeeds[i].name) {
1039 msg_perr("Error: Invalid spispeed value: '%s'.\n", spispeed);
1040 free(spispeed);
1041 return 1;
1042 }
1043 free(spispeed);
1044 }
1045
hailfingerf76cc322010-11-09 22:00:31 +00001046 voltage = extract_programmer_param("voltage");
1047 if (voltage) {
1048 millivolt = parse_voltage(voltage);
1049 free(voltage);
uwe8d342eb2011-07-28 08:13:25 +00001050 if (millivolt < 0)
hailfingerf76cc322010-11-09 22:00:31 +00001051 return 1;
hailfingerf76cc322010-11-09 22:00:31 +00001052 msg_pinfo("Setting voltage to %i mV\n", millivolt);
1053 }
David Hendricksfe05e742015-08-15 17:29:39 -07001054
1055 device = extract_programmer_param("device");
1056 if (device) {
1057 char *dev_suffix;
1058 errno = 0;
1059 usedevice = strtol(device, &dev_suffix, 10);
1060 if (errno != 0 || device == dev_suffix) {
1061 msg_perr("Error: Could not convert 'device'.\n");
1062 free(device);
Simon Glassd01002b2015-01-08 05:44:16 -07001063 return 1;
1064 }
David Hendricksfe05e742015-08-15 17:29:39 -07001065 if (usedevice < 0 || usedevice > UINT_MAX) {
1066 msg_perr("Error: Value for 'device' is out of range.\n");
1067 free(device);
1068 return 1;
1069 }
1070 if (strlen(dev_suffix) > 0) {
1071 msg_perr("Error: Garbage following 'device' value.\n");
1072 free(device);
1073 return 1;
1074 }
1075 msg_pinfo("Using device %li.\n", usedevice);
Simon Glassd01002b2015-01-08 05:44:16 -07001076 }
David Hendricksfe05e742015-08-15 17:29:39 -07001077 free(device);
1078
1079 target_str = extract_programmer_param("target");
1080 if (target_str) {
1081 char *target_suffix;
1082 errno = 0;
1083 target = strtol(target_str, &target_suffix, 10);
1084 if (errno != 0 || target_str == target_suffix) {
1085 msg_perr("Error: Could not convert 'target'.\n");
1086 free(target_str);
1087 return 1;
1088 }
1089 if (target < 1 || target > 2) {
1090 msg_perr("Error: Value for 'target' is out of range.\n");
1091 free(target_str);
1092 return 1;
1093 }
1094 if (strlen(target_suffix) > 0) {
1095 msg_perr("Error: Garbage following 'target' value.\n");
1096 free(target_str);
1097 return 1;
1098 }
1099 msg_pinfo("Using target %li.\n", target);
1100 }
1101 free(target_str);
hailfingerf76cc322010-11-09 22:00:31 +00001102
hailfingerdfb32a02010-01-19 11:15:48 +00001103 /* Here comes the USB stuff. */
David Hendricksf9ecb452015-11-04 15:40:27 -08001104 libusb_init(&usb_ctx);
1105 if (!usb_ctx) {
1106 msg_perr("Could not initialize libusb!\n");
hailfingerdfb32a02010-01-19 11:15:48 +00001107 return 1;
1108 }
David Hendricksf9ecb452015-11-04 15:40:27 -08001109 dediprog_handle = get_device_by_vid_pid_number(0x0483, 0xdada, (unsigned int) usedevice);
David Hendricksfe05e742015-08-15 17:29:39 -07001110 if (!dediprog_handle) {
David Hendricks22593802015-11-13 12:59:30 -08001111 msg_perr("Could not find a Dediprog programmer on USB!\n");
David Hendricksf9ecb452015-11-04 15:40:27 -08001112 libusb_exit(usb_ctx);
David Hendricksfe05e742015-08-15 17:29:39 -07001113 return 1;
1114 }
David Hendricksf9ecb452015-11-04 15:40:27 -08001115 ret = libusb_set_configuration(dediprog_handle, 1);
1116 if (ret != 0) {
1117 msg_perr("Could not set USB device configuration: %i %s\n", ret, libusb_error_name(ret));
1118 libusb_close(dediprog_handle);
1119 libusb_exit(usb_ctx);
hailfingerfb6287d2010-11-16 21:25:29 +00001120 return 1;
1121 }
David Hendricksf9ecb452015-11-04 15:40:27 -08001122 ret = libusb_claim_interface(dediprog_handle, 0);
hailfingerfb6287d2010-11-16 21:25:29 +00001123 if (ret < 0) {
David Hendricksf9ecb452015-11-04 15:40:27 -08001124 msg_perr("Could not claim USB device interface %i: %i %s\n", 0, ret, libusb_error_name(ret));
1125 libusb_close(dediprog_handle);
1126 libusb_exit(usb_ctx);
hailfingerfb6287d2010-11-16 21:25:29 +00001127 return 1;
1128 }
David Hendricksfe05e742015-08-15 17:29:39 -07001129
dhendrix0ffc2eb2011-06-14 01:35:36 +00001130 if (register_shutdown(dediprog_shutdown, NULL))
1131 return 1;
1132
David Hendricks28fbdfb2015-08-15 18:04:37 -07001133 /* Try reading the devicestring. If that fails and the device is old
1134 * (FW < 6.0.0) then we need to try the "set voltage" command and then
1135 * attempt to read the devicestring again. */
1136 if (dediprog_check_devicestring()) {
1137 if (dediprog_set_voltage())
1138 return 1;
1139 if (dediprog_check_devicestring())
1140 return 1;
1141 }
David Hendricksfe05e742015-08-15 17:29:39 -07001142
David Hendricksd7468582015-11-12 15:21:12 -08001143 /* SF100 firmware exposes only one endpoint for in/out, SF600 firmware
1144 exposes separate endpoints for in and out. */
1145 dediprog_in_endpoint = 2;
1146 if (dediprog_devicetype == DEV_SF100)
1147 dediprog_out_endpoint = 2;
1148 else
1149 dediprog_out_endpoint = 1;
1150
David Hendricks93784b42016-08-09 17:00:38 -07001151
David Hendrickse4c73662015-11-20 16:26:07 -08001152 /* Set some LEDs as soon as possible to indicate activity.
David Hendricksfe05e742015-08-15 17:29:39 -07001153 * Because knowing the firmware version is required to set the LEDs correctly we need to this after
1154 * dediprog_setup() has queried the device and set dediprog_firmwareversion. */
David Hendrickse4c73662015-11-20 16:26:07 -08001155 dediprog_set_leds(LED_PASS | LED_BUSY);
David Hendricksfe05e742015-08-15 17:29:39 -07001156
David Hendrickscd20ea42015-11-17 22:33:35 -08001157 /* FIXME: need to do this so buses_supported gets SPI */
1158 register_spi_programmer(&spi_programmer_dediprog);
David Hendricks93784b42016-08-09 17:00:38 -07001159
David Hendricksfe05e742015-08-15 17:29:39 -07001160 /* Select target/socket, frequency and VCC. */
1161 if (set_target_flash(FLASH_TYPE_APPLICATION_FLASH_1) ||
1162 dediprog_set_spi_speed(spispeed_idx) ||
David Hendricks93784b42016-08-09 17:00:38 -07001163 dediprog_set_spi_voltage(millivolt, voltage ? 0 : 1)) {
Simon Glasse53cc1d2015-01-08 05:48:51 -07001164 dediprog_set_leds(LED_ERROR);
hailfingerdfb32a02010-01-19 11:15:48 +00001165 return 1;
stepan4c06de72011-01-28 09:00:15 +00001166 }
hailfingerdfb32a02010-01-19 11:15:48 +00001167
David Hendrickscf453d82015-11-16 20:19:57 -08001168 if (dediprog_leave_standalone_mode())
1169 return 1;
1170
David Hendricks93784b42016-08-09 17:00:38 -07001171
David Hendricksfe05e742015-08-15 17:29:39 -07001172 dediprog_set_leds(LED_NONE);
stepan4c06de72011-01-28 09:00:15 +00001173
hailfingerdfb32a02010-01-19 11:15:48 +00001174 return 0;
1175}
David Hendricksfe05e742015-08-15 17:29:39 -07001176