summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Anastasio <shawnanastasio@yahoo.com>2017-12-31 00:17:15 -0600
committerNico Huber <nico.h@gmx.de>2018-01-26 15:23:10 +0000
commit2b5adfb1b656dd6a6efbf45a7a411c87840c5394 (patch)
treecfc4bf09d45d4ad59b645c0cadaec9507ba5c152
parent25fde40f8594b1c13ba7a4c3a605b96b200a4e11 (diff)
downloadflashrom-2b5adfb1b656dd6a6efbf45a7a411c87840c5394.tar.gz
flashrom-2b5adfb1b656dd6a6efbf45a7a411c87840c5394.tar.bz2
flashrom-2b5adfb1b656dd6a6efbf45a7a411c87840c5394.zip
buspirate_spi: Add support for variable serial speeds
This patch sets the default baud rate for communication between the host device and the Bus Pirate for hardware versions 3.0 and greater to 2M baud. It also introduces the ability to manually set the baud rate via the added 'serialspeed' programmer parameter. This is done in two parts. Firstly, the requested serial speed is looked up in a table to determine the appropriate clock divisor and the divisor is sent to the bus pirate. Then, the system's baud rate for the selected serial port is set using serial.c's 'serialport_config'. This function's prototype had to be added to programmer.h. In testing, using the 2M baud rate was able to significantly decrease flash times (down from 20+ minutes to less than 2 minutes for an 8MB flash). Change-Id: I3706f17a94fdf056063f2ad4a5f0a219665cdcbf Signed-off-by: Shawn Anastasio <shawnanastasio@yahoo.com> Reviewed-on: https://review.coreboot.org/23057 Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r--buspirate_spi.c132
-rw-r--r--flashrom.8.tmpl12
-rw-r--r--programmer.h1
3 files changed, 134 insertions, 11 deletions
diff --git a/buspirate_spi.c b/buspirate_spi.c
index 6f4c6d06e..f82541552 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -30,16 +30,18 @@
/* Change this to #define if you want to test without a serial implementation */
#undef FAKE_COMMUNICATION
-struct buspirate_spispeeds {
+struct buspirate_speeds {
const char *name;
const int speed;
};
+#define BP_DEFAULTBAUD 115200
+
#ifndef FAKE_COMMUNICATION
static int buspirate_serialport_setup(char *dev)
{
/* 115200bps, 8 databits, no parity, 1 stopbit */
- sp_fd = sp_openserport(dev, 115200);
+ sp_fd = sp_openserport(dev, BP_DEFAULTBAUD);
if (sp_fd == SER_INV_FD)
return 1;
return 0;
@@ -146,7 +148,7 @@ static struct spi_master spi_master_buspirate = {
.write_aai = default_spi_write_aai,
};
-static const struct buspirate_spispeeds spispeeds[] = {
+static const struct buspirate_speeds spispeeds[] = {
{"30k", 0x0},
{"125k", 0x1},
{"250k", 0x2},
@@ -155,7 +157,16 @@ static const struct buspirate_spispeeds spispeeds[] = {
{"2.6M", 0x5},
{"4M", 0x6},
{"8M", 0x7},
- {NULL, 0x0},
+ {NULL, 0x0}
+};
+
+static const struct buspirate_speeds serialspeeds[] = {
+ {"115200", 115200},
+ {"230400", 230400},
+ {"250000", 250000},
+ {"2000000", 2000000},
+ {"2M", 2000000},
+ {NULL, 0}
};
static int buspirate_spi_shutdown(void *data)
@@ -199,15 +210,26 @@ out_shutdown:
}
#define BP_FWVERSION(a,b) ((a) << 8 | (b))
+#define BP_HWVERSION(a,b) BP_FWVERSION(a,b)
+
+/**
+ * The Bus Pirate's PIC microcontroller supports custom baud rates by manually specifying a
+ * clock divisor that can be calculated with the formula (16000000 / (4 * baud)) - 1.
+ */
+#define BP_DIVISOR(baud) ((4000000/(baud)) - 1)
int buspirate_spi_init(void)
{
char *tmp;
char *dev;
int i;
+ int cnt;
unsigned int fw_version_major = 0;
unsigned int fw_version_minor = 0;
+ unsigned int hw_version_major = 0;
+ unsigned int hw_version_minor = 0;
int spispeed = 0x7;
+ int serialspeed_index = -1;
int ret = 0;
int pullup = 0;
@@ -234,6 +256,20 @@ int buspirate_spi_init(void)
}
free(tmp);
+ /* Extract serialspeed paramater */
+ tmp = extract_programmer_param("serialspeed");
+ if (tmp) {
+ for (i = 0; serialspeeds[i].name; i++) {
+ if (!strncasecmp(serialspeeds[i].name, tmp, strlen(serialspeeds[i].name))) {
+ serialspeed_index = i;
+ break;
+ }
+ }
+ if (!serialspeeds[i].name)
+ msg_perr("Invalid serial speed %s, using default.\n", tmp);
+ }
+ free(tmp);
+
tmp = extract_programmer_param("pullups");
if (tmp) {
if (strcasecmp("on", tmp) == 0)
@@ -313,7 +349,20 @@ int buspirate_spi_init(void)
break;
}
bp_commbuf[i] = '\0';
- msg_pdbg("Detected Bus Pirate hardware %s\n", bp_commbuf);
+ msg_pdbg("Detected Bus Pirate hardware ");
+ if (bp_commbuf[0] != 'v')
+ msg_pdbg("(unknown version number format)");
+ else if (!strchr("0123456789", bp_commbuf[1]))
+ msg_pdbg("(unknown version number format)");
+ else {
+ hw_version_major = strtoul((char *)bp_commbuf + 1, &tmp, 10);
+ while ((*tmp != '\0') && !strchr("0123456789", *tmp))
+ tmp++;
+ hw_version_minor = strtoul(tmp, NULL, 10);
+ msg_pdbg("%u.%u", hw_version_major, hw_version_minor);
+ }
+ msg_pdbg2(" (\"%s\")", bp_commbuf);
+ msg_pdbg("\n");
if ((ret = buspirate_wait_for_string(bp_commbuf, "irmware ")))
return ret;
@@ -342,7 +391,7 @@ int buspirate_spi_init(void)
if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>")))
return ret;
-
+
/* Tell the user about missing SPI binary mode in firmware 2.3 and older. */
if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(2, 4)) {
msg_pinfo("Bus Pirate firmware 2.3 and older does not support binary SPI access.\n");
@@ -352,7 +401,7 @@ int buspirate_spi_init(void)
/* Use fast SPI mode in firmware 5.5 and newer. */
if (BP_FWVERSION(fw_version_major, fw_version_minor) >= BP_FWVERSION(5, 5)) {
- msg_pdbg("Using SPI command set v2.\n");
+ msg_pdbg("Using SPI command set v2.\n");
/* Sensible default buffer size. */
if (buspirate_commbuf_grow(260 + 5))
return ERROR_OOM;
@@ -379,10 +428,71 @@ int buspirate_spi_init(void)
msg_pinfo("It is recommended to upgrade to firmware 6.2 or newer.\n");
spispeed = 0x4;
}
-
+
/* This works because speeds numbering starts at 0 and is contiguous. */
msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed].name);
+ /* Set 2M baud serial speed by default on hardware 3.0 and newer if a custom speed was not set */
+ if (serialspeed_index == -1 && BP_HWVERSION(hw_version_major, hw_version_minor) >= BP_HWVERSION(3, 0)) {
+ serialspeed_index = ARRAY_SIZE(serialspeeds) - 2;
+ msg_pdbg("Bus Pirate v3 or newer detected. Set serial speed to 2M baud.\n");
+ }
+
+ /* Set custom serial speed if specified */
+ if (serialspeed_index != -1) {
+ if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(5, 5)) {
+ /* This feature requires firmware 5.5 or newer */
+ msg_perr("Bus Pirate firmware 5.4 and older does not support custom serial speeds."
+ "Using default speed of 115200 baud.\n");
+ } else if (serialspeeds[serialspeed_index].speed != BP_DEFAULTBAUD) {
+ /* Set the serial speed to match the user's choice if it doesn't already */
+
+ if (BP_HWVERSION(hw_version_major, hw_version_minor) < BP_HWVERSION(3, 0))
+ msg_pwarn("Increased serial speeds may not work on older (<3.0) Bus Pirates."
+ " Continue at your own risk.\n");
+
+ /* Enter baud rate configuration mode */
+ cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "b\n");
+ if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0)))
+ return ret;
+ if ((ret = buspirate_wait_for_string(bp_commbuf, ">")))
+ return ret;
+
+ /* Enter manual clock divisor entry mode */
+ cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "10\n");
+ if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0)))
+ return ret;
+ if ((ret = buspirate_wait_for_string(bp_commbuf, ">")))
+ return ret;
+
+ /* Set the clock divisor to the value calculated from the user's input */
+ cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "%d\n",
+ BP_DIVISOR(serialspeeds[serialspeed_index].speed));
+
+ if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0)))
+ return ret;
+ sleep(1);
+
+ /* Reconfigure the host's serial baud rate to the new value */
+ if ((ret = serialport_config(sp_fd, serialspeeds[serialspeed_index].speed))) {
+ msg_perr("Unable to configure system baud rate to specified value.");
+ return ret;
+ }
+
+ /* Return to the main prompt */
+ bp_commbuf[0] = ' ';
+ if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
+ return ret;
+ if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>")))
+ return ret;
+
+ msg_pdbg("Serial speed is %d baud\n", serialspeeds[serialspeed_index].speed);
+ }
+
+ }
+
+
+
/* Enter raw bitbang mode */
for (i = 0; i < 20; i++) {
bp_commbuf[0] = 0x00;
@@ -434,7 +544,7 @@ int buspirate_spi_init(void)
msg_perr("Protocol error while setting SPI speed!\n");
return 1;
}
-
+
/* Set SPI config: output type, idle, clock edge, sample */
bp_commbuf[0] = 0x80 | 0xa;
ret = buspirate_sendrecv(bp_commbuf, 1, 1);
@@ -534,7 +644,7 @@ static int buspirate_spi_send_command_v2(struct flashctx *flash, unsigned int wr
bp_commbuf[i++] = (readcnt >> 8) & 0xff;
bp_commbuf[i++] = readcnt & 0xff;
memcpy(bp_commbuf + i, writearr, writecnt);
-
+
ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt);
if (ret) {
@@ -551,4 +661,4 @@ static int buspirate_spi_send_command_v2(struct flashctx *flash, unsigned int wr
memcpy(readarr, bp_commbuf + 1, readcnt);
return ret;
-}
+} \ No newline at end of file
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index 143d76c5f..160011374 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -817,6 +817,18 @@ can be
.BR 30k ", " 125k ", " 250k ", " 1M ", " 2M ", " 2.6M ", " 4M " or " 8M
(in Hz). The default is the maximum frequency of 8 MHz.
.sp
+The baud rate for communication between the host and the Bus Pirate can be specified with the optional
+.B serialspeed
+parameter. Syntax is
+.sp
+.B " flashrom -p buspirate_spi:serialspeed=baud
+.sp
+where
+.B baud
+can be
+.BR 115200 ", " 230400 ", " 250000 " or " 2000000 " (" 2M ")."
+The default is 2M baud for Bus Pirate hardware version 3.0 and greater, and 115200 otherwise.
+.sp
An optional pullups parameter specifies the use of the Bus Pirate internal pull-up resistors. This may be
needed if you are working with a flash ROM chip that you have physically removed from the board. Syntax is
.sp
diff --git a/programmer.h b/programmer.h
index 8736449ba..139f4fafa 100644
--- a/programmer.h
+++ b/programmer.h
@@ -759,6 +759,7 @@ typedef int fdtype;
void sp_flush_incoming(void);
fdtype sp_openserport(char *dev, int baud);
extern fdtype sp_fd;
+int serialport_config(fdtype fd, int baud);
int serialport_shutdown(void *data);
int serialport_write(const unsigned char *buf, unsigned int writecnt);
int serialport_write_nonblock(const unsigned char *buf, unsigned int writecnt, unsigned int timeout, unsigned int *really_wrote);