summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);