flashrom 

flashrom Svn Source Tree

Root/trunk/buspirate_spi.c

1/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009, 2010, 2011, 2012 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; 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>
21#include <strings.h>
22#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <unistd.h>
26#include "flash.h"
27#include "programmer.h"
28#include "spi.h"
29
30/* Change this to #define if you want to test without a serial implementation */
31#undef FAKE_COMMUNICATION
32
33struct buspirate_spispeeds {
34const char *name;
35const int speed;
36};
37
38#ifndef FAKE_COMMUNICATION
39static int buspirate_serialport_setup(char *dev)
40{
41/* 115200bps, 8 databits, no parity, 1 stopbit */
42sp_fd = sp_openserport(dev, 115200);
43 if (sp_fd == SER_INV_FD)
44return 1;
45return 0;
46}
47#else
48#define buspirate_serialport_setup(...) 0
49#define serialport_shutdown(...) 0
50#define serialport_write(...) 0
51#define serialport_read(...) 0
52#define sp_flush_incoming(...) 0
53#endif
54
55static unsigned char *bp_commbuf = NULL;
56static int bp_commbufsize = 0;
57
58static int buspirate_commbuf_grow(int bufsize)
59{
60unsigned char *tmpbuf;
61
62/* Never shrink. realloc() calls are expensive. */
63if (bufsize <= bp_commbufsize)
64return 0;
65
66tmpbuf = realloc(bp_commbuf, bufsize);
67if (!tmpbuf) {
68/* Keep the existing buffer because memory is already tight. */
69msg_perr("Out of memory!\n");
70return ERROR_OOM;
71}
72
73bp_commbuf = tmpbuf;
74bp_commbufsize = bufsize;
75return 0;
76}
77
78static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt,
79 unsigned int readcnt)
80{
81int i, ret = 0;
82
83msg_pspew("%s: write %i, read %i ", __func__, writecnt, readcnt);
84if (!writecnt && !readcnt) {
85msg_perr("Zero length command!\n");
86return 1;
87}
88if (writecnt)
89msg_pspew("Sending");
90for (i = 0; i < writecnt; i++)
91msg_pspew(" 0x%02x", buf[i]);
92#ifdef FAKE_COMMUNICATION
93/* Placate the caller for now. */
94if (readcnt) {
95buf[0] = 0x01;
96memset(buf + 1, 0xff, readcnt - 1);
97}
98ret = 0;
99#else
100if (writecnt)
101ret = serialport_write(buf, writecnt);
102if (ret)
103return ret;
104if (readcnt)
105ret = serialport_read(buf, readcnt);
106if (ret)
107return ret;
108#endif
109if (readcnt)
110msg_pspew(", receiving");
111for (i = 0; i < readcnt; i++)
112msg_pspew(" 0x%02x", buf[i]);
113msg_pspew("\n");
114return 0;
115}
116
117static int buspirate_wait_for_string(unsigned char *buf, char *key)
118{
119unsigned int keylen = strlen(key);
120int ret;
121
122ret = buspirate_sendrecv(buf, 0, keylen);
123while (!ret) {
124if (!memcmp(buf, key, keylen))
125return 0;
126memmove(buf, buf + 1, keylen - 1);
127ret = buspirate_sendrecv(buf + keylen - 1, 0, 1);
128}
129return ret;
130}
131
132static int buspirate_spi_send_command_v1(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
133 const unsigned char *writearr, unsigned char *readarr);
134static int buspirate_spi_send_command_v2(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
135 const unsigned char *writearr, unsigned char *readarr);
136
137static struct spi_master spi_master_buspirate = {
138.type= SPI_CONTROLLER_BUSPIRATE,
139.max_data_read= MAX_DATA_UNSPECIFIED,
140.max_data_write= MAX_DATA_UNSPECIFIED,
141.command= NULL,
142.multicommand= default_spi_send_multicommand,
143.read= default_spi_read,
144.write_256= default_spi_write_256,
145.write_aai= default_spi_write_aai,
146};
147
148static const struct buspirate_spispeeds spispeeds[] = {
149{"30k",0x0},
150{"125k",0x1},
151{"250k",0x2},
152{"1M",0x3},
153{"2M",0x4},
154{"2.6M",0x5},
155{"4M",0x6},
156{"8M",0x7},
157{NULL,0x0},
158};
159
160static int buspirate_spi_shutdown(void *data)
161{
162int ret = 0, ret2 = 0;
163/* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */
164
165/* Exit raw SPI mode (enter raw bitbang mode) */
166bp_commbuf[0] = 0x00;
167if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
168goto out_shutdown;
169if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
170goto out_shutdown;
171if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
172goto out_shutdown;
173msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
174if (bp_commbuf[0] != '1') {
175msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
176ret = 1;
177goto out_shutdown;
178}
179/* Reset Bus Pirate (return to user terminal) */
180bp_commbuf[0] = 0x0f;
181ret = buspirate_sendrecv(bp_commbuf, 1, 0);
182
183out_shutdown:
184/* Shut down serial port communication */
185ret2 = serialport_shutdown(NULL);
186/* Keep the oldest error, it is probably the best indicator. */
187if (ret2 && !ret)
188ret = ret2;
189bp_commbufsize = 0;
190free(bp_commbuf);
191bp_commbuf = NULL;
192if (ret)
193msg_pdbg("Bus Pirate shutdown failed.\n");
194else
195msg_pdbg("Bus Pirate shutdown completed.\n");
196
197return ret;
198}
199
200#define BP_FWVERSION(a,b)((a) << 8 | (b))
201
202int buspirate_spi_init(void)
203{
204char *tmp;
205char *dev;
206int i;
207unsigned int fw_version_major = 0;
208unsigned int fw_version_minor = 0;
209int spispeed = 0x7;
210int ret = 0;
211int pullup = 0;
212
213dev = extract_programmer_param("dev");
214if (dev && !strlen(dev)) {
215free(dev);
216dev = NULL;
217}
218if (!dev) {
219msg_perr("No serial device given. Use flashrom -p buspirate_spi:dev=/dev/ttyUSB0\n");
220return 1;
221}
222
223tmp = extract_programmer_param("spispeed");
224if (tmp) {
225for (i = 0; spispeeds[i].name; i++) {
226if (!strncasecmp(spispeeds[i].name, tmp, strlen(spispeeds[i].name))) {
227spispeed = spispeeds[i].speed;
228break;
229}
230}
231if (!spispeeds[i].name)
232msg_perr("Invalid SPI speed, using default.\n");
233}
234free(tmp);
235
236tmp = extract_programmer_param("pullups");
237if (tmp) {
238if (strcasecmp("on", tmp) == 0)
239pullup = 1;
240else if (strcasecmp("off", tmp) == 0)
241; // ignore
242else
243msg_perr("Invalid pullups state, not using them.\n");
244}
245free(tmp);
246
247/* Default buffer size is 19: 16 bytes data, 3 bytes control. */
248#define DEFAULT_BUFSIZE (16 + 3)
249bp_commbuf = malloc(DEFAULT_BUFSIZE);
250if (!bp_commbuf) {
251bp_commbufsize = 0;
252msg_perr("Out of memory!\n");
253free(dev);
254return ERROR_OOM;
255}
256bp_commbufsize = DEFAULT_BUFSIZE;
257
258ret = buspirate_serialport_setup(dev);
259free(dev);
260if (ret) {
261bp_commbufsize = 0;
262free(bp_commbuf);
263bp_commbuf = NULL;
264return ret;
265}
266
267if (register_shutdown(buspirate_spi_shutdown, NULL) != 0) {
268bp_commbufsize = 0;
269free(bp_commbuf);
270bp_commbuf = NULL;
271return 1;
272}
273
274/* This is the brute force version, but it should work.
275 * It is likely to fail if a previous flashrom run was aborted during a write with the new SPI commands
276 * in firmware v5.5 because that firmware may wait for up to 4096 bytes of input before responding to
277 * 0x00 again. The obvious workaround (sending 4096 bytes of \0) may cause significant startup delays.
278 */
279for (i = 0; i < 20; i++) {
280/* Enter raw bitbang mode */
281bp_commbuf[0] = 0x00;
282/* Send the command, don't read the response. */
283ret = buspirate_sendrecv(bp_commbuf, 1, 0);
284if (ret)
285return ret;
286/* The old way to handle responses from a Bus Pirate already in BBIO mode was to flush any
287 * response which came in over serial. Unfortunately that does not work reliably on Linux
288 * with FTDI USB-serial.
289 */
290//sp_flush_incoming();
291/* The Bus Pirate can't handle UART input buffer overflow in BBIO mode, and sending a sequence
292 * of 0x00 too fast apparently triggers such an UART input buffer overflow.
293 */
294internal_sleep(10000);
295}
296/* We know that 20 commands of \0 should elicit at least one BBIO1 response. */
297if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
298return ret;
299
300/* Reset the Bus Pirate. */
301bp_commbuf[0] = 0x0f;
302/* Send the command, don't read the response. */
303if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
304return ret;
305if ((ret = buspirate_wait_for_string(bp_commbuf, "irate ")))
306return ret;
307/* Read the hardware version string. Last byte of the buffer is reserved for \0. */
308for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) {
309if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1)))
310return ret;
311if (strchr("\r\n\t ", bp_commbuf[i]))
312break;
313}
314bp_commbuf[i] = '\0';
315msg_pdbg("Detected Bus Pirate hardware %s\n", bp_commbuf);
316
317if ((ret = buspirate_wait_for_string(bp_commbuf, "irmware ")))
318return ret;
319/* Read the firmware version string. Last byte of the buffer is reserved for \0. */
320for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) {
321if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1)))
322return ret;
323if (strchr("\r\n\t ", bp_commbuf[i]))
324break;
325}
326bp_commbuf[i] = '\0';
327msg_pdbg("Detected Bus Pirate firmware ");
328if (bp_commbuf[0] != 'v')
329msg_pdbg("(unknown version number format)");
330else if (!strchr("0123456789", bp_commbuf[1]))
331msg_pdbg("(unknown version number format)");
332else {
333fw_version_major = strtoul((char *)bp_commbuf + 1, &tmp, 10);
334while ((*tmp != '\0') && !strchr("0123456789", *tmp))
335tmp++;
336fw_version_minor = strtoul(tmp, NULL, 10);
337msg_pdbg("%u.%u", fw_version_major, fw_version_minor);
338}
339msg_pdbg2(" (\"%s\")", bp_commbuf);
340msg_pdbg("\n");
341
342if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>")))
343return ret;
344
345/* Tell the user about missing SPI binary mode in firmware 2.3 and older. */
346if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(2, 4)) {
347msg_pinfo("Bus Pirate firmware 2.3 and older does not support binary SPI access.\n");
348msg_pinfo("Please upgrade to the latest firmware (at least 2.4).\n");
349return SPI_PROGRAMMER_ERROR;
350}
351
352/* Use fast SPI mode in firmware 5.5 and newer. */
353if (BP_FWVERSION(fw_version_major, fw_version_minor) >= BP_FWVERSION(5, 5)) {
354msg_pdbg("Using SPI command set v2.\n");
355/* Sensible default buffer size. */
356if (buspirate_commbuf_grow(260 + 5))
357return ERROR_OOM;
358spi_master_buspirate.max_data_read = 2048;
359spi_master_buspirate.max_data_write = 256;
360spi_master_buspirate.command = buspirate_spi_send_command_v2;
361} else {
362msg_pinfo("Bus Pirate firmware 5.4 and older does not support fast SPI access.\n");
363msg_pinfo("Reading/writing a flash chip may take hours.\n");
364msg_pinfo("It is recommended to upgrade to firmware 5.5 or newer.\n");
365/* Sensible default buffer size. */
366if (buspirate_commbuf_grow(16 + 3))
367return ERROR_OOM;
368spi_master_buspirate.max_data_read = 12;
369spi_master_buspirate.max_data_write = 12;
370spi_master_buspirate.command = buspirate_spi_send_command_v1;
371}
372
373/* Workaround for broken speed settings in firmware 6.1 and older. */
374if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(6, 2))
375if (spispeed > 0x4) {
376msg_perr("Bus Pirate firmware 6.1 and older does not support SPI speeds above 2 MHz. "
377 "Limiting speed to 2 MHz.\n");
378msg_pinfo("It is recommended to upgrade to firmware 6.2 or newer.\n");
379spispeed = 0x4;
380}
381
382/* This works because speeds numbering starts at 0 and is contiguous. */
383msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed].name);
384
385/* Enter raw bitbang mode */
386for (i = 0; i < 20; i++) {
387bp_commbuf[0] = 0x00;
388if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
389return ret;
390}
391if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
392return ret;
393if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
394return ret;
395msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
396if (bp_commbuf[0] != '1') {
397msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
398return 1;
399}
400/* Enter raw SPI mode */
401bp_commbuf[0] = 0x01;
402ret = buspirate_sendrecv(bp_commbuf, 1, 0);
403if ((ret = buspirate_wait_for_string(bp_commbuf, "SPI")))
404return ret;
405if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
406return ret;
407msg_pdbg("Raw SPI mode version %c\n", bp_commbuf[0]);
408if (bp_commbuf[0] != '1') {
409msg_perr("Can't handle raw SPI mode version %c!\n", bp_commbuf[0]);
410return 1;
411}
412
413/* Initial setup (SPI peripherals config): Enable power, CS high, AUX */
414bp_commbuf[0] = 0x40 | 0x0b;
415if (pullup == 1) {
416bp_commbuf[0] |= (1 << 2);
417msg_pdbg("Enabling pull-up resistors.\n");
418}
419ret = buspirate_sendrecv(bp_commbuf, 1, 1);
420if (ret)
421return 1;
422if (bp_commbuf[0] != 0x01) {
423msg_perr("Protocol error while setting power/CS/AUX(/Pull-up resistors)!\n");
424return 1;
425}
426
427/* Set SPI speed */
428bp_commbuf[0] = 0x60 | spispeed;
429ret = buspirate_sendrecv(bp_commbuf, 1, 1);
430if (ret)
431return 1;
432if (bp_commbuf[0] != 0x01) {
433msg_perr("Protocol error while setting SPI speed!\n");
434return 1;
435}
436
437/* Set SPI config: output type, idle, clock edge, sample */
438bp_commbuf[0] = 0x80 | 0xa;
439ret = buspirate_sendrecv(bp_commbuf, 1, 1);
440if (ret)
441return 1;
442if (bp_commbuf[0] != 0x01) {
443msg_perr("Protocol error while setting SPI config!\n");
444return 1;
445}
446
447/* De-assert CS# */
448bp_commbuf[0] = 0x03;
449ret = buspirate_sendrecv(bp_commbuf, 1, 1);
450if (ret)
451return 1;
452if (bp_commbuf[0] != 0x01) {
453msg_perr("Protocol error while raising CS#!\n");
454return 1;
455}
456
457register_spi_master(&spi_master_buspirate);
458
459return 0;
460}
461
462static int buspirate_spi_send_command_v1(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
463 const unsigned char *writearr, unsigned char *readarr)
464{
465unsigned int i = 0;
466int ret = 0;
467
468if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
469return SPI_INVALID_LENGTH;
470
471/* 3 bytes extra for CS#, len, CS#. */
472if (buspirate_commbuf_grow(writecnt + readcnt + 3))
473return ERROR_OOM;
474
475/* Assert CS# */
476bp_commbuf[i++] = 0x02;
477
478bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1);
479memcpy(bp_commbuf + i, writearr, writecnt);
480i += writecnt;
481memset(bp_commbuf + i, 0, readcnt);
482
483i += readcnt;
484/* De-assert CS# */
485bp_commbuf[i++] = 0x03;
486
487ret = buspirate_sendrecv(bp_commbuf, i, i);
488
489if (ret) {
490msg_perr("Bus Pirate communication error!\n");
491return SPI_GENERIC_ERROR;
492}
493
494if (bp_commbuf[0] != 0x01) {
495msg_perr("Protocol error while lowering CS#!\n");
496return SPI_GENERIC_ERROR;
497}
498
499if (bp_commbuf[1] != 0x01) {
500msg_perr("Protocol error while reading/writing SPI!\n");
501return SPI_GENERIC_ERROR;
502}
503
504if (bp_commbuf[i - 1] != 0x01) {
505msg_perr("Protocol error while raising CS#!\n");
506return SPI_GENERIC_ERROR;
507}
508
509/* Skip CS#, length, writearr. */
510memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
511
512return ret;
513}
514
515static int buspirate_spi_send_command_v2(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
516 const unsigned char *writearr, unsigned char *readarr)
517{
518int i = 0, ret = 0;
519
520if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096)
521return SPI_INVALID_LENGTH;
522
523/* 5 bytes extra for command, writelen, readlen.
524 * 1 byte extra for Ack/Nack.
525 */
526if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1)))
527return ERROR_OOM;
528
529/* Combined SPI write/read. */
530bp_commbuf[i++] = 0x04;
531bp_commbuf[i++] = (writecnt >> 8) & 0xff;
532bp_commbuf[i++] = writecnt & 0xff;
533bp_commbuf[i++] = (readcnt >> 8) & 0xff;
534bp_commbuf[i++] = readcnt & 0xff;
535memcpy(bp_commbuf + i, writearr, writecnt);
536
537ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt);
538
539if (ret) {
540msg_perr("Bus Pirate communication error!\n");
541return SPI_GENERIC_ERROR;
542}
543
544if (bp_commbuf[0] != 0x01) {
545msg_perr("Protocol error while sending SPI write/read!\n");
546return SPI_GENERIC_ERROR;
547}
548
549/* Skip Ack. */
550memcpy(readarr, bp_commbuf + 1, readcnt);
551
552return ret;
553}

Archive Download this file

Revision: HEAD