blob: d00277e701f26874f3551f0f4d3997491560037f [file] [log] [blame]
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +00001/*
2 * This file is part of the flashrom project.
3 *
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +00004 * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <stdio.h>
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000021#include <string.h>
22#include <stdlib.h>
23#include <ctype.h>
Carl-Daniel Hailfingerd2f007f2010-09-16 22:34:25 +000024#include <unistd.h>
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000025#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000026#include "programmer.h"
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000027#include "spi.h"
28
29/* Change this to #define if you want to test without a serial implementation */
30#undef FAKE_COMMUNICATION
31
Carl-Daniel Hailfingerc4224842011-06-09 20:06:34 +000032struct buspirate_spispeeds {
33 const char *name;
34 const int speed;
35};
36
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000037#ifndef FAKE_COMMUNICATION
Carl-Daniel Hailfingerad3cc552010-07-03 11:02:10 +000038static int buspirate_serialport_setup(char *dev)
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000039{
40 /* 115200bps, 8 databits, no parity, 1 stopbit */
41 sp_fd = sp_openserport(dev, 115200);
Niklas Söderlund2a95e872012-07-30 19:42:33 +000042 if (sp_fd < 0)
43 return 1;
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000044 return 0;
45}
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000046#else
47#define buspirate_serialport_setup(...) 0
Carl-Daniel Hailfingerefa151e2010-01-06 16:09:10 +000048#define serialport_shutdown(...) 0
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000049#define serialport_write(...) 0
50#define serialport_read(...) 0
Patrick Georgi3b6237d2010-01-06 19:09:40 +000051#define sp_flush_incoming(...) 0
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000052#endif
53
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +000054static unsigned char *bp_commbuf = NULL;
55static int bp_commbufsize = 0;
56
57static int buspirate_commbuf_grow(int bufsize)
58{
59 unsigned char *tmpbuf;
60
61 /* Never shrink. realloc() calls are expensive. */
62 if (bufsize <= bp_commbufsize)
63 return 0;
64
65 tmpbuf = realloc(bp_commbuf, bufsize);
66 if (!tmpbuf) {
67 /* Keep the existing buffer because memory is already tight. */
68 msg_perr("Out of memory!\n");
69 return ERROR_OOM;
70 }
71
72 bp_commbuf = tmpbuf;
73 bp_commbufsize = bufsize;
74 return 0;
75}
76
Uwe Hermann91f4afa2011-07-28 08:13:25 +000077static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt,
78 unsigned int readcnt)
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000079{
80 int i, ret = 0;
81
Sean Nelson84f7bce2010-01-09 23:56:41 +000082 msg_pspew("%s: write %i, read %i ", __func__, writecnt, readcnt);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000083 if (!writecnt && !readcnt) {
Sean Nelson84f7bce2010-01-09 23:56:41 +000084 msg_perr("Zero length command!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000085 return 1;
86 }
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +000087 if (writecnt)
88 msg_pspew("Sending");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000089 for (i = 0; i < writecnt; i++)
Sean Nelson84f7bce2010-01-09 23:56:41 +000090 msg_pspew(" 0x%02x", buf[i]);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +000091#ifdef FAKE_COMMUNICATION
92 /* Placate the caller for now. */
93 if (readcnt) {
94 buf[0] = 0x01;
95 memset(buf + 1, 0xff, readcnt - 1);
96 }
97 ret = 0;
98#else
99 if (writecnt)
100 ret = serialport_write(buf, writecnt);
101 if (ret)
102 return ret;
103 if (readcnt)
104 ret = serialport_read(buf, readcnt);
105 if (ret)
106 return ret;
107#endif
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000108 if (readcnt)
109 msg_pspew(", receiving");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000110 for (i = 0; i < readcnt; i++)
Sean Nelson84f7bce2010-01-09 23:56:41 +0000111 msg_pspew(" 0x%02x", buf[i]);
112 msg_pspew("\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000113 return 0;
114}
115
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000116static int buspirate_wait_for_string(unsigned char *buf, char *key)
117{
118 unsigned int keylen = strlen(key);
119 int ret;
120
121 ret = buspirate_sendrecv(buf, 0, keylen);
122 while (!ret) {
123 if (!memcmp(buf, key, keylen))
124 return 0;
125 memmove(buf, buf + 1, keylen - 1);
126 ret = buspirate_sendrecv(buf + keylen - 1, 0, 1);
127 }
128 return ret;
129}
130
131static int buspirate_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
132 const unsigned char *writearr, unsigned char *readarr);
Michael Karcherb9dbe482011-05-11 17:07:07 +0000133
134static const struct spi_programmer spi_programmer_buspirate = {
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000135 .type = SPI_CONTROLLER_BUSPIRATE,
136 .max_data_read = 12,
137 .max_data_write = 12,
138 .command = buspirate_spi_send_command,
139 .multicommand = default_spi_send_multicommand,
140 .read = default_spi_read,
141 .write_256 = default_spi_write_256,
Nico Huber7bca1262012-06-15 22:28:12 +0000142 .write_aai = default_spi_write_aai,
Michael Karcherb9dbe482011-05-11 17:07:07 +0000143};
144
Carl-Daniel Hailfingerd5b28fa2009-11-24 18:27:10 +0000145static const struct buspirate_spispeeds spispeeds[] = {
146 {"30k", 0x0},
147 {"125k", 0x1},
148 {"250k", 0x2},
149 {"1M", 0x3},
150 {"2M", 0x4},
151 {"2.6M", 0x5},
152 {"4M", 0x6},
153 {"8M", 0x7},
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000154 {NULL, 0x0},
Carl-Daniel Hailfingerd5b28fa2009-11-24 18:27:10 +0000155};
156
David Hendricks8bb20212011-06-14 01:35:36 +0000157static int buspirate_spi_shutdown(void *data)
158{
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000159 int ret = 0, ret2 = 0;
160 /* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */
David Hendricks8bb20212011-06-14 01:35:36 +0000161
162 /* Exit raw SPI mode (enter raw bitbang mode) */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000163 bp_commbuf[0] = 0x00;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000164 if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000165 goto out_shutdown;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000166 if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000167 goto out_shutdown;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000168 if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
169 goto out_shutdown;
170 msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
171 if (bp_commbuf[0] != '1') {
172 msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000173 ret = 1;
174 goto out_shutdown;
David Hendricks8bb20212011-06-14 01:35:36 +0000175 }
176 /* Reset Bus Pirate (return to user terminal) */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000177 bp_commbuf[0] = 0x0f;
178 ret = buspirate_sendrecv(bp_commbuf, 1, 0);
David Hendricks8bb20212011-06-14 01:35:36 +0000179
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000180out_shutdown:
David Hendricks8bb20212011-06-14 01:35:36 +0000181 /* Shut down serial port communication */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000182 ret2 = serialport_shutdown(NULL);
183 /* Keep the oldest error, it is probably the best indicator. */
184 if (ret2 && !ret)
185 ret = ret2;
186 bp_commbufsize = 0;
187 free(bp_commbuf);
188 bp_commbuf = NULL;
David Hendricks8bb20212011-06-14 01:35:36 +0000189 if (ret)
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000190 msg_pdbg("Bus Pirate shutdown failed.\n");
191 else
192 msg_pdbg("Bus Pirate shutdown completed.\n");
David Hendricks8bb20212011-06-14 01:35:36 +0000193
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000194 return ret;
David Hendricks8bb20212011-06-14 01:35:36 +0000195}
196
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000197#define BP_FWVERSION(a,b) ((a) << 8 | (b))
198
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000199int buspirate_spi_init(void)
200{
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000201 char *dev = NULL;
Carl-Daniel Hailfingerd5b28fa2009-11-24 18:27:10 +0000202 char *speed = NULL;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000203 char *tmp;
204 unsigned int fw_version_major = 0;
205 unsigned int fw_version_minor = 0;
Carl-Daniel Hailfinger082c8b52011-08-15 19:54:20 +0000206 int spispeed = 0x7;
207 int ret = 0;
208 int i;
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000209
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000210 dev = extract_programmer_param("dev");
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000211 if (dev && !strlen(dev)) {
212 free(dev);
213 dev = NULL;
214 }
215 if (!dev) {
216 msg_perr("No serial device given. Use flashrom -p buspirate_spi:dev=/dev/ttyUSB0\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000217 return 1;
218 }
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000219
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000220 speed = extract_programmer_param("spispeed");
Carl-Daniel Hailfingerd5b28fa2009-11-24 18:27:10 +0000221 if (speed) {
222 for (i = 0; spispeeds[i].name; i++)
223 if (!strncasecmp(spispeeds[i].name, speed,
224 strlen(spispeeds[i].name))) {
225 spispeed = spispeeds[i].speed;
226 break;
227 }
228 if (!spispeeds[i].name)
Sean Nelson84f7bce2010-01-09 23:56:41 +0000229 msg_perr("Invalid SPI speed, using default.\n");
Carl-Daniel Hailfingerd5b28fa2009-11-24 18:27:10 +0000230 }
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000231 free(speed);
232
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000233 /* Default buffer size is 19: 16 bytes data, 3 bytes control. */
234#define DEFAULT_BUFSIZE (16 + 3)
235 bp_commbuf = malloc(DEFAULT_BUFSIZE);
236 if (!bp_commbuf) {
237 bp_commbufsize = 0;
238 msg_perr("Out of memory!\n");
239 return ERROR_OOM;
240 }
241 bp_commbufsize = DEFAULT_BUFSIZE;
242
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000243 ret = buspirate_serialport_setup(dev);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000244 free(dev);
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000245 if (ret) {
246 bp_commbufsize = 0;
247 free(bp_commbuf);
248 bp_commbuf = NULL;
249 return ret;
250 }
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000251
David Hendricks8bb20212011-06-14 01:35:36 +0000252 if (register_shutdown(buspirate_spi_shutdown, NULL))
253 return 1;
254
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000255 /* This is the brute force version, but it should work. */
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000256 for (i = 0; i < 20; i++) {
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000257 /* Enter raw bitbang mode */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000258 bp_commbuf[0] = 0x00;
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000259 /* Send the command, don't read the response. */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000260 ret = buspirate_sendrecv(bp_commbuf, 1, 0);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000261 if (ret)
262 return ret;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000263 /* The old way to handle responses from a Bus Pirate already in BBIO mode was to flush any
264 * response which came in over serial. Unfortunately that does not work reliably on Linux
265 * with FTDI USB-serial.
266 */
267 //sp_flush_incoming();
268 /* The Bus Pirate can't handle UART input buffer overflow in BBIO mode, and sending a sequence
269 * of 0x00 too fast apparently triggers such an UART input buffer overflow.
270 */
271 usleep(10000);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000272 }
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000273 /* We know that 20 commands of \0 should elicit at least one BBIO1 response. */
274 if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000275 return ret;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000276
277 /* Reset the Bus Pirate. */
278 bp_commbuf[0] = 0x0f;
279 /* Send the command, don't read the response. */
280 if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
281 return ret;
282 if ((ret = buspirate_wait_for_string(bp_commbuf, "irate ")))
283 return ret;
284 /* Read the hardware version string. Last byte of the buffer is reserved for \0. */
285 for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) {
286 if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1)))
287 return ret;
288 if (strchr("\r\n\t ", bp_commbuf[i]))
289 break;
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000290 }
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000291 bp_commbuf[i] = '\0';
292 msg_pdbg("Detected Bus Pirate hardware %s\n", bp_commbuf);
293
294 if ((ret = buspirate_wait_for_string(bp_commbuf, "irmware ")))
295 return ret;
296 /* Read the firmware version string. Last byte of the buffer is reserved for \0. */
297 for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) {
298 if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1)))
299 return ret;
300 if (strchr("\r\n\t ", bp_commbuf[i]))
301 break;
302 }
303 bp_commbuf[i] = '\0';
304 msg_pdbg("Detected Bus Pirate firmware ");
305 if (bp_commbuf[0] != 'v')
306 msg_pdbg("(unknown version number format)");
307 else if (!strchr("0123456789", bp_commbuf[1]))
308 msg_pdbg("(unknown version number format)");
309 else {
310 fw_version_major = strtoul((char *)bp_commbuf + 1, &tmp, 10);
311 while ((*tmp != '\0') && !strchr("0123456789", *tmp))
312 tmp++;
313 fw_version_minor = strtoul(tmp, NULL, 10);
314 msg_pdbg("%u.%u", fw_version_major, fw_version_minor);
315 }
316 msg_pdbg2(" (\"%s\")", bp_commbuf);
317 msg_pdbg("\n");
318
319 if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>")))
320 return ret;
321
322 /* Tell the user about missing SPI binary mode in firmware 2.3 and older. */
323 if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(2, 4)) {
324 msg_pinfo("Bus Pirate firmware 2.3 and older does not support binary SPI access.\n");
325 msg_pinfo("Please upgrade to the latest firmware (at least 2.4).\n");
326 return SPI_PROGRAMMER_ERROR;
327 }
328
329 /* Workaround for broken speed settings in firmware 6.1 and older. */
330 if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(6, 2))
331 if (spispeed > 0x4) {
332 msg_perr("Bus Pirate firmware 6.1 and older does not support SPI speeds above 2 MHz. "
333 "Limiting speed to 2 MHz.\n");
334 msg_pinfo("It is recommended to upgrade to firmware 6.2 or newer.\n");
335 spispeed = 0x4;
336 }
337
338 /* This works because speeds numbering starts at 0 and is contiguous. */
339 msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed].name);
340
341 /* Enter raw bitbang mode */
342 for (i = 0; i < 20; i++) {
343 bp_commbuf[0] = 0x00;
344 if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
345 return ret;
346 }
347 if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
348 return ret;
349 if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
350 return ret;
351 msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
352 if (bp_commbuf[0] != '1') {
353 msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000354 return 1;
355 }
356 /* Enter raw SPI mode */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000357 bp_commbuf[0] = 0x01;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000358 ret = buspirate_sendrecv(bp_commbuf, 1, 0);
359 if ((ret = buspirate_wait_for_string(bp_commbuf, "SPI")))
Carl-Daniel Hailfingerd2f007f2010-09-16 22:34:25 +0000360 return ret;
Carl-Daniel Hailfingera16a8922012-08-17 17:30:43 +0000361 if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
362 return ret;
363 msg_pdbg("Raw SPI mode version %c\n", bp_commbuf[0]);
364 if (bp_commbuf[0] != '1') {
365 msg_perr("Can't handle raw SPI mode version %c!\n", bp_commbuf[0]);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000366 return 1;
367 }
368
369 /* Initial setup (SPI peripherals config): Enable power, CS high, AUX */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000370 bp_commbuf[0] = 0x40 | 0xb;
371 ret = buspirate_sendrecv(bp_commbuf, 1, 1);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000372 if (ret)
373 return 1;
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000374 if (bp_commbuf[0] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000375 msg_perr("Protocol error while setting power/CS/AUX!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000376 return 1;
377 }
378
Carl-Daniel Hailfingerd5b28fa2009-11-24 18:27:10 +0000379 /* Set SPI speed */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000380 bp_commbuf[0] = 0x60 | spispeed;
381 ret = buspirate_sendrecv(bp_commbuf, 1, 1);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000382 if (ret)
383 return 1;
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000384 if (bp_commbuf[0] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000385 msg_perr("Protocol error while setting SPI speed!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000386 return 1;
387 }
388
389 /* Set SPI config: output type, idle, clock edge, sample */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000390 bp_commbuf[0] = 0x80 | 0xa;
391 ret = buspirate_sendrecv(bp_commbuf, 1, 1);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000392 if (ret)
393 return 1;
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000394 if (bp_commbuf[0] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000395 msg_perr("Protocol error while setting SPI config!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000396 return 1;
397 }
398
399 /* De-assert CS# */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000400 bp_commbuf[0] = 0x03;
401 ret = buspirate_sendrecv(bp_commbuf, 1, 1);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000402 if (ret)
403 return 1;
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000404 if (bp_commbuf[0] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000405 msg_perr("Protocol error while raising CS#!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000406 return 1;
407 }
408
Michael Karcherb9dbe482011-05-11 17:07:07 +0000409 register_spi_programmer(&spi_programmer_buspirate);
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000410
411 return 0;
412}
413
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000414static int buspirate_spi_send_command(struct flashctx *flash,
415 unsigned int writecnt,
416 unsigned int readcnt,
417 const unsigned char *writearr,
418 unsigned char *readarr)
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000419{
Stefan Taunerc69c9c82011-11-23 09:13:48 +0000420 unsigned int i = 0;
421 int ret = 0;
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000422
423 if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
424 return SPI_INVALID_LENGTH;
425
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000426 /* 3 bytes extra for CS#, len, CS#. */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000427 if (buspirate_commbuf_grow(writecnt + readcnt + 3))
428 return ERROR_OOM;
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000429
430 /* Assert CS# */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000431 bp_commbuf[i++] = 0x02;
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000432
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000433 bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1);
434 memcpy(bp_commbuf + i, writearr, writecnt);
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000435 i += writecnt;
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000436 memset(bp_commbuf + i, 0, readcnt);
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000437
438 i += readcnt;
439 /* De-assert CS# */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000440 bp_commbuf[i++] = 0x03;
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000441
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000442 ret = buspirate_sendrecv(bp_commbuf, i, i);
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000443
444 if (ret) {
445 msg_perr("Bus Pirate communication error!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000446 return SPI_GENERIC_ERROR;
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000447 }
448
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000449 if (bp_commbuf[0] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000450 msg_perr("Protocol error while lowering CS#!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000451 return SPI_GENERIC_ERROR;
452 }
453
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000454 if (bp_commbuf[1] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000455 msg_perr("Protocol error while reading/writing SPI!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000456 return SPI_GENERIC_ERROR;
457 }
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000458
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000459 if (bp_commbuf[i - 1] != 0x01) {
Sean Nelson84f7bce2010-01-09 23:56:41 +0000460 msg_perr("Protocol error while raising CS#!\n");
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000461 return SPI_GENERIC_ERROR;
462 }
463
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000464 /* Skip CS#, length, writearr. */
Carl-Daniel Hailfinger316fdfb2012-06-08 15:27:47 +0000465 memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
Carl-Daniel Hailfinger04e18be2010-07-29 16:24:09 +0000466
Carl-Daniel Hailfinger5cca01f2009-11-24 00:20:03 +0000467 return ret;
468}