From d5b28fae1da48233753a19d3fa007c204786ec8c Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Tue, 24 Nov 2009 18:27:10 +0000 Subject: 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. Tested-by: Sean Nelson Corresponding to flashrom svn r776. Signed-off-by: Carl-Daniel Hailfinger Acked-by: Sean Nelson --- buspirate_spi.c | 54 ++++++++++++++++++++++++++++++++++-------------------- flash.h | 5 +++++ flashrom.8 | 12 ++++++++++++ flashrom.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi.c | 3 +++ 5 files changed, 108 insertions(+), 20 deletions(-) diff --git a/buspirate_spi.c b/buspirate_spi.c index 259e434..a1c8265 100644 --- a/buspirate_spi.c +++ b/buspirate_spi.c @@ -131,34 +131,37 @@ int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt, unsigned int r 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 @@ int buspirate_spi_init(void) "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 @@ int buspirate_spi_init(void) 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_send_command(unsigned int writecnt, unsigned int readcnt, 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. */ diff --git a/flash.h b/flash.h index b271b8a..008af28 100644 --- a/flash.h +++ b/flash.h @@ -488,6 +488,10 @@ int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); 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 read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len); 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); diff --git a/flashrom.8 b/flashrom.8 index 3986f75..011840c 100644 --- a/flashrom.8 +++ b/flashrom.8 @@ -152,6 +152,8 @@ Specify the programmer device. Currently supported are: .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 @@ syntax and for IP, you have to use 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. diff --git a/flashrom.c b/flashrom.c index 7e681cc..fffedd6 100644 --- a/flashrom.c +++ b/flashrom.c @@ -336,6 +336,60 @@ char *strcat_realloc(char *dest, const char *src) 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) { diff --git a/spi.c b/spi.c index f117c8f..14beed7 100644 --- a/spi.c +++ b/spi.c @@ -319,6 +319,9 @@ int probe_spi_rdid4(struct flashchip *flash) #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"); -- cgit v1.1