Author: hailfinger
Date: 2009-11-24 19:27:10 +0100 (Tue, 24 Nov 2009)
New Revision: 776
Modified:
trunk/buspirate_spi.c
trunk/flash.h
trunk/flashrom.8
trunk/flashrom.c
trunk/spi.c
Log:
Add the ability to set Bus Pirate SPI speed via the command line.
Example usage:
flashrom -p buspiratespi:spispeed=2.6MHz,dev=/dev/foo
flashrom -p buspiratespi:dev=/dev/foo,spispeed=2.6M
Refactor programmer option parsing (this allows cleanups in other
programmers as well).
Increase SPI read size from 8 to 12 bytes (current single-transaction
limit of the Bus Pirate raw SPI protocol).
Add Bus Pirate to the list of programmers supporting 4 byte RDID.
Add Bus Pirate syntax to the man page.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006(a)gmx.net>
Acked-by: Sean Nelson <audiohacked(a)gmail.com>
Tested-by: Sean Nelson <audiohacked(a)gmail.com>
Modified: trunk/buspirate_spi.c
===================================================================
--- trunk/buspirate_spi.c 2009-11-24 02:11:08 UTC (rev 775)
+++ trunk/buspirate_spi.c 2009-11-24 18:27:10 UTC (rev 776)
@@ -131,34 +131,37 @@
return 0;
}
+static const struct buspirate_spispeeds spispeeds[] = {
+ {"30k", 0x0},
+ {"125k", 0x1},
+ {"250k", 0x2},
+ {"1M", 0x3},
+ {"2M", 0x4},
+ {"2.6M", 0x5},
+ {"4M", 0x6},
+ {"8M", 0x7},
+ {NULL, 0x0}
+};
+
int buspirate_spi_init(void)
{
unsigned char buf[512];
int ret = 0;
int i;
- char *devpos = NULL;
char *dev = NULL;
- int devlen;
+ char *speed = NULL;
+ int spispeed = 0x7;
if (programmer_param && !strlen(programmer_param)) {
free(programmer_param);
programmer_param = NULL;
}
if (programmer_param) {
- devpos = strstr(programmer_param, "dev=");
- if (devpos) {
- devpos += 4;
- devlen = strcspn(devpos, ",:");
- if (devlen) {
- dev = malloc(devlen + 1);
- if (!dev) {
- fprintf(stderr, "Out of memory!\n");
- exit(1);
- }
- strncpy(dev, devpos, devlen);
- dev[devlen] = '\0';
- }
- }
+ dev = extract_param(&programmer_param, "dev=", ",:");
+ speed = extract_param(&programmer_param, "spispeed=", ",:");
+ if (strlen(programmer_param))
+ fprintf(stderr, "Unhandled programmer parameters: %s\n",
+ programmer_param);
free(programmer_param);
programmer_param = NULL;
}
@@ -167,6 +170,18 @@
"buspiratespi:dev=/dev/ttyUSB0\n");
return 1;
}
+ if (speed) {
+ for (i = 0; spispeeds[i].name; i++)
+ if (!strncasecmp(spispeeds[i].name, speed,
+ strlen(spispeeds[i].name))) {
+ spispeed = spispeeds[i].speed;
+ break;
+ }
+ if (!spispeeds[i].name)
+ fprintf(stderr, "Invalid SPI speed, using default.\n");
+ }
+ /* This works because speeds numbering starts at 0 and is contiguous. */
+ printf_debug("SPI speed is %sHz\n", spispeeds[spispeed].name);
ret = buspirate_serialport_setup(dev);
if (ret)
@@ -224,8 +239,8 @@
return 1;
}
- /* Set speed to 8 MHz */
- buf[0] = 0x60 | 0x7;
+ /* Set SPI speed */
+ buf[0] = 0x60 | spispeed;
ret = buspirate_sendrecv(buf, 1, 1);
if (ret)
return 1;
@@ -351,8 +366,7 @@
int buspirate_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
- /* Maximum read length is 12 bytes, use 8 for now. */
- return spi_read_chunked(flash, buf, start, len, 8);
+ return spi_read_chunked(flash, buf, start, len, 12);
}
/* We could do 12-byte writes, but for now we use the generic 1-byte code. */
Modified: trunk/flash.h
===================================================================
--- trunk/flash.h 2009-11-24 02:11:08 UTC (rev 775)
+++ trunk/flash.h 2009-11-24 18:27:10 UTC (rev 776)
@@ -488,6 +488,10 @@
int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf);
/* buspirate_spi.c */
+struct buspirate_spispeeds {
+ const char *name;
+ const int speed;
+};
int buspirate_spi_init(void);
int buspirate_spi_shutdown(void);
int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
@@ -503,6 +507,7 @@
int erase_flash(struct flashchip *flash);
int min(int a, int b);
int max(int a, int b);
+char *extract_param(char **haystack, char *needle, char *delim);
int check_erased_range(struct flashchip *flash, int start, int len);
int verify_range(struct flashchip *flash, uint8_t *cmpbuf, int start, int len, char *message);
char *strcat_realloc(char *dest, const char *src);
Modified: trunk/flashrom.8
===================================================================
--- trunk/flashrom.8 2009-11-24 02:11:08 UTC (rev 775)
+++ trunk/flashrom.8 2009-11-24 18:27:10 UTC (rev 776)
@@ -152,6 +152,8 @@
.sp
.BR "* serprog" " (for flash ROMs attached to Urja's AVR programmer)"
.sp
+.BR "* buspiratespi" " (for flash ROMs attached to a Bus Pirate)"
+.sp
The dummy programmer has an optional parameter specifying the bus types it
should support. For that you have to use the
.B "flashrom -p dummy:type"
@@ -219,6 +221,16 @@
instead. More information about serprog is available in serprog-protocol.txt in
the source distribution.
.sp
+The buspiratespi programmer has a required dev parameter specifying the Bus
+Pirate device node and an optional spispeed parameter specifying the frequency
+of the SPI bus. The parameter delimiter is a comma. Syntax is
+.B "flashrom -p buspiratespi:dev=/dev/device,spispeed=frequency"
+where
+.B frequency
+can be any of
+.B 30k 125k 250k 1M 2M 2.6M 4M 8M
+(in Hz).
+.sp
Support for some programmers can be disabled at compile time.
.B "flashrom -h"
lists all supported programmers.
Modified: trunk/flashrom.c
===================================================================
--- trunk/flashrom.c 2009-11-24 02:11:08 UTC (rev 775)
+++ trunk/flashrom.c 2009-11-24 18:27:10 UTC (rev 776)
@@ -336,6 +336,60 @@
return dest;
}
+/* This is a somewhat hacked function similar in some ways to strtok().
+ * It will look for needle in haystack, return a copy of needle and remove
+ * everything from the first occurrence of needle to the next delimiter
+ * from haystack.
+ */
+char *extract_param(char **haystack, char *needle, char *delim)
+{
+ char *param_pos, *rest, *tmp;
+ char *dev = NULL;
+ int devlen;
+
+ param_pos = strstr(*haystack, needle);
+ do {
+ if (!param_pos)
+ return NULL;
+ /* Beginning of the string? */
+ if (param_pos == *haystack)
+ break;
+ /* After a delimiter? */
+ if (strchr(delim, *(param_pos - 1)))
+ break;
+ /* Continue searching. */
+ param_pos++;
+ param_pos = strstr(param_pos, needle);
+ } while (1);
+
+ if (param_pos) {
+ param_pos += strlen(needle);
+ devlen = strcspn(param_pos, delim);
+ if (devlen) {
+ dev = malloc(devlen + 1);
+ if (!dev) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+ strncpy(dev, param_pos, devlen);
+ dev[devlen] = '\0';
+ }
+ rest = param_pos + devlen;
+ rest += strspn(rest, delim);
+ param_pos -= strlen(needle);
+ memmove(param_pos, rest, strlen(rest) + 1);
+ tmp = realloc(*haystack, strlen(*haystack) + 1);
+ if (!tmp) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+ *haystack = tmp;
+ }
+
+
+ return dev;
+}
+
/* start is an offset to the base address of the flash chip */
int check_erased_range(struct flashchip *flash, int start, int len)
{
Modified: trunk/spi.c
===================================================================
--- trunk/spi.c 2009-11-24 02:11:08 UTC (rev 775)
+++ trunk/spi.c 2009-11-24 18:27:10 UTC (rev 776)
@@ -319,6 +319,9 @@
#if DUMMY_SUPPORT == 1
case SPI_CONTROLLER_DUMMY:
#endif
+#if BUSPIRATE_SPI_SUPPORT == 1
+ case SPI_CONTROLLER_BUSPIRATE:
+#endif
return probe_spi_rdid_generic(flash, 4);
default:
printf_debug("4b ID not supported on this SPI controller\n");