[flashrom] [PATCH 2/3] Shuffle code around (no other changes)
Michael Karcher
flashrom at mkarcher.dialup.fu-berlin.de
Thu May 5 03:04:28 CEST 2011
This is to prepare the SPI registration patch without needing to do forward
declarations.
Signed-off-by: Michael Karcher <flashrom at mkarcher.dialup.fu-berlin.de>
---
bitbang_spi.c | 84 +++++++++---------
buspirate_spi.c | 182 +++++++++++++++++++-------------------
dummyflasher.c | 264 +++++++++++++++++++++++++++---------------------------
ft2232_spi.c | 170 ++++++++++++++++++------------------
it85spi.c | 103 +++++++++++-----------
it87spi.c | 242 +++++++++++++++++++++++++-------------------------
wbsio_spi.c | 94 ++++++++++----------
7 files changed, 569 insertions(+), 570 deletions(-)
diff --git a/bitbang_spi.c b/bitbang_spi.c
index d63c769..be30944 100644
--- a/bitbang_spi.c
+++ b/bitbang_spi.c
@@ -64,6 +64,48 @@ static void bitbang_spi_release_bus(void)
bitbang_spi_master->release_bus();
}
+static uint8_t bitbang_spi_readwrite_byte(uint8_t val)
+{
+ uint8_t ret = 0;
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ bitbang_spi_set_mosi((val >> i) & 1);
+ programmer_delay(bitbang_spi_half_period);
+ bitbang_spi_set_sck(1);
+ ret <<= 1;
+ ret |= bitbang_spi_get_miso();
+ programmer_delay(bitbang_spi_half_period);
+ bitbang_spi_set_sck(0);
+ }
+ return ret;
+}
+
+int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ int i;
+
+ /* FIXME: Run bitbang_spi_request_bus here or in programmer init?
+ * Requesting and releasing the SPI bus is handled in here to allow the
+ * programmer to use its own SPI engine for native accesses.
+ */
+ bitbang_spi_request_bus();
+ bitbang_spi_set_cs(0);
+ for (i = 0; i < writecnt; i++)
+ bitbang_spi_readwrite_byte(writearr[i]);
+ for (i = 0; i < readcnt; i++)
+ readarr[i] = bitbang_spi_readwrite_byte(0);
+
+ programmer_delay(bitbang_spi_half_period);
+ bitbang_spi_set_cs(1);
+ programmer_delay(bitbang_spi_half_period);
+ /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */
+ bitbang_spi_release_bus();
+
+ return 0;
+}
+
int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod)
{
/* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type,
@@ -109,45 +151,3 @@ int bitbang_spi_shutdown(const struct bitbang_spi_master *master)
bitbang_spi_master = NULL;
return 0;
}
-
-static uint8_t bitbang_spi_readwrite_byte(uint8_t val)
-{
- uint8_t ret = 0;
- int i;
-
- for (i = 7; i >= 0; i--) {
- bitbang_spi_set_mosi((val >> i) & 1);
- programmer_delay(bitbang_spi_half_period);
- bitbang_spi_set_sck(1);
- ret <<= 1;
- ret |= bitbang_spi_get_miso();
- programmer_delay(bitbang_spi_half_period);
- bitbang_spi_set_sck(0);
- }
- return ret;
-}
-
-int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- int i;
-
- /* FIXME: Run bitbang_spi_request_bus here or in programmer init?
- * Requesting and releasing the SPI bus is handled in here to allow the
- * programmer to use its own SPI engine for native accesses.
- */
- bitbang_spi_request_bus();
- bitbang_spi_set_cs(0);
- for (i = 0; i < writecnt; i++)
- bitbang_spi_readwrite_byte(writearr[i]);
- for (i = 0; i < readcnt; i++)
- readarr[i] = bitbang_spi_readwrite_byte(0);
-
- programmer_delay(bitbang_spi_half_period);
- bitbang_spi_set_cs(1);
- programmer_delay(bitbang_spi_half_period);
- /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */
- bitbang_spi_release_bus();
-
- return 0;
-}
diff --git a/buspirate_spi.c b/buspirate_spi.c
index e7a7a10..89f529d 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -81,6 +81,97 @@ static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt, unsigne
return 0;
}
+int buspirate_spi_shutdown(void)
+{
+ unsigned char buf[5];
+ int ret = 0;
+
+ /* Exit raw SPI mode (enter raw bitbang mode) */
+ buf[0] = 0x00;
+ ret = buspirate_sendrecv(buf, 1, 5);
+ if (ret)
+ return ret;
+ if (memcmp(buf, "BBIO", 4)) {
+ msg_perr("Entering raw bitbang mode failed!\n");
+ return 1;
+ }
+ msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
+ if (buf[4] != '1') {
+ msg_perr("Can't handle raw bitbang mode version %c!\n",
+ buf[4]);
+ return 1;
+ }
+ /* Reset Bus Pirate (return to user terminal) */
+ buf[0] = 0x0f;
+ ret = buspirate_sendrecv(buf, 1, 0);
+ if (ret)
+ return ret;
+
+ /* Shut down serial port communication */
+ ret = serialport_shutdown();
+ if (ret)
+ return ret;
+ msg_pdbg("Bus Pirate shutdown completed.\n");
+
+ return 0;
+}
+
+int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ static unsigned char *buf = NULL;
+ int i = 0, ret = 0;
+
+ if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
+ return SPI_INVALID_LENGTH;
+
+ /* 3 bytes extra for CS#, len, CS#. */
+ buf = realloc(buf, writecnt + readcnt + 3);
+ if (!buf) {
+ msg_perr("Out of memory!\n");
+ exit(1); // -1
+ }
+
+ /* Assert CS# */
+ buf[i++] = 0x02;
+
+ buf[i++] = 0x10 | (writecnt + readcnt - 1);
+ memcpy(buf + i, writearr, writecnt);
+ i += writecnt;
+ memset(buf + i, 0, readcnt);
+
+ i += readcnt;
+ /* De-assert CS# */
+ buf[i++] = 0x03;
+
+ ret = buspirate_sendrecv(buf, i, i);
+
+ if (ret) {
+ msg_perr("Bus Pirate communication error!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ if (buf[0] != 0x01) {
+ msg_perr("Protocol error while lowering CS#!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ if (buf[1] != 0x01) {
+ msg_perr("Protocol error while reading/writing SPI!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ if (buf[i - 1] != 0x01) {
+ msg_perr("Protocol error while raising CS#!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ /* Skip CS#, length, writearr. */
+ memcpy(readarr, buf + 2 + writecnt, readcnt);
+
+ return ret;
+}
+
static const struct buspirate_spispeeds spispeeds[] = {
{"30k", 0x0},
{"125k", 0x1},
@@ -235,94 +326,3 @@ int buspirate_spi_init(void)
return 0;
}
-
-int buspirate_spi_shutdown(void)
-{
- unsigned char buf[5];
- int ret = 0;
-
- /* Exit raw SPI mode (enter raw bitbang mode) */
- buf[0] = 0x00;
- ret = buspirate_sendrecv(buf, 1, 5);
- if (ret)
- return ret;
- if (memcmp(buf, "BBIO", 4)) {
- msg_perr("Entering raw bitbang mode failed!\n");
- return 1;
- }
- msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
- if (buf[4] != '1') {
- msg_perr("Can't handle raw bitbang mode version %c!\n",
- buf[4]);
- return 1;
- }
- /* Reset Bus Pirate (return to user terminal) */
- buf[0] = 0x0f;
- ret = buspirate_sendrecv(buf, 1, 0);
- if (ret)
- return ret;
-
- /* Shut down serial port communication */
- ret = serialport_shutdown();
- if (ret)
- return ret;
- msg_pdbg("Bus Pirate shutdown completed.\n");
-
- return 0;
-}
-
-int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- static unsigned char *buf = NULL;
- int i = 0, ret = 0;
-
- if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
- return SPI_INVALID_LENGTH;
-
- /* 3 bytes extra for CS#, len, CS#. */
- buf = realloc(buf, writecnt + readcnt + 3);
- if (!buf) {
- msg_perr("Out of memory!\n");
- exit(1); // -1
- }
-
- /* Assert CS# */
- buf[i++] = 0x02;
-
- buf[i++] = 0x10 | (writecnt + readcnt - 1);
- memcpy(buf + i, writearr, writecnt);
- i += writecnt;
- memset(buf + i, 0, readcnt);
-
- i += readcnt;
- /* De-assert CS# */
- buf[i++] = 0x03;
-
- ret = buspirate_sendrecv(buf, i, i);
-
- if (ret) {
- msg_perr("Bus Pirate communication error!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (buf[0] != 0x01) {
- msg_perr("Protocol error while lowering CS#!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (buf[1] != 0x01) {
- msg_perr("Protocol error while reading/writing SPI!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (buf[i - 1] != 0x01) {
- msg_perr("Protocol error while raising CS#!\n");
- return SPI_GENERIC_ERROR;
- }
-
- /* Skip CS#, length, writearr. */
- memcpy(readarr, buf + 2 + writecnt, readcnt);
-
- return ret;
-}
diff --git a/dummyflasher.c b/dummyflasher.c
index b6e67db..c4c9c4e 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -60,138 +60,6 @@ static int emu_jedec_ce_c7_size = 0;
static int spi_write_256_chunksize = 256;
-int dummy_init(void)
-{
- char *bustext = NULL;
- char *tmp = NULL;
-#if EMULATE_CHIP
- struct stat image_stat;
-#endif
-
- msg_pspew("%s\n", __func__);
-
- bustext = extract_programmer_param("bus");
- msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default");
- if (!bustext)
- bustext = strdup("parallel+lpc+fwh+spi");
- /* Convert the parameters to lowercase. */
- tolower_string(bustext);
-
- buses_supported = CHIP_BUSTYPE_NONE;
- if (strstr(bustext, "parallel")) {
- buses_supported |= CHIP_BUSTYPE_PARALLEL;
- msg_pdbg("Enabling support for %s flash.\n", "parallel");
- }
- if (strstr(bustext, "lpc")) {
- buses_supported |= CHIP_BUSTYPE_LPC;
- msg_pdbg("Enabling support for %s flash.\n", "LPC");
- }
- if (strstr(bustext, "fwh")) {
- buses_supported |= CHIP_BUSTYPE_FWH;
- msg_pdbg("Enabling support for %s flash.\n", "FWH");
- }
- if (strstr(bustext, "spi")) {
- buses_supported |= CHIP_BUSTYPE_SPI;
- spi_controller = SPI_CONTROLLER_DUMMY;
- msg_pdbg("Enabling support for %s flash.\n", "SPI");
- }
- if (buses_supported == CHIP_BUSTYPE_NONE)
- msg_pdbg("Support for all flash bus types disabled.\n");
- free(bustext);
-
- tmp = extract_programmer_param("spi_write_256_chunksize");
- if (tmp) {
- spi_write_256_chunksize = atoi(tmp);
- free(tmp);
- if (spi_write_256_chunksize < 1) {
- msg_perr("invalid spi_write_256_chunksize\n");
- return 1;
- }
- }
-
-#if EMULATE_CHIP
- tmp = extract_programmer_param("emulate");
- if (!tmp) {
- msg_pdbg("Not emulating any flash chip.\n");
- /* Nothing else to do. */
- return 0;
- }
-#if EMULATE_SPI_CHIP
- if (!strcmp(tmp, "M25P10.RES")) {
- emu_chip = EMULATE_ST_M25P10_RES;
- emu_chip_size = 128 * 1024;
- emu_max_byteprogram_size = 128;
- emu_max_aai_size = 0;
- emu_jedec_se_size = 0;
- emu_jedec_be_52_size = 0;
- emu_jedec_be_d8_size = 32 * 1024;
- emu_jedec_ce_60_size = 0;
- emu_jedec_ce_c7_size = emu_chip_size;
- msg_pdbg("Emulating ST M25P10.RES SPI flash chip (RES, page "
- "write)\n");
- }
- if (!strcmp(tmp, "SST25VF040.REMS")) {
- emu_chip = EMULATE_SST_SST25VF040_REMS;
- emu_chip_size = 512 * 1024;
- emu_max_byteprogram_size = 1;
- emu_max_aai_size = 0;
- emu_jedec_se_size = 4 * 1024;
- emu_jedec_be_52_size = 32 * 1024;
- emu_jedec_be_d8_size = 0;
- emu_jedec_ce_60_size = emu_chip_size;
- emu_jedec_ce_c7_size = 0;
- msg_pdbg("Emulating SST SST25VF040.REMS SPI flash chip (REMS, "
- "byte write)\n");
- }
- if (!strcmp(tmp, "SST25VF032B")) {
- emu_chip = EMULATE_SST_SST25VF032B;
- emu_chip_size = 4 * 1024 * 1024;
- emu_max_byteprogram_size = 1;
- emu_max_aai_size = 2;
- emu_jedec_se_size = 4 * 1024;
- emu_jedec_be_52_size = 32 * 1024;
- emu_jedec_be_d8_size = 64 * 1024;
- emu_jedec_ce_60_size = emu_chip_size;
- emu_jedec_ce_c7_size = emu_chip_size;
- msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI "
- "write)\n");
- }
-#endif
- if (emu_chip == EMULATE_NONE) {
- msg_perr("Invalid chip specified for emulation: %s\n", tmp);
- free(tmp);
- return 1;
- }
- free(tmp);
- flashchip_contents = malloc(emu_chip_size);
- if (!flashchip_contents) {
- msg_perr("Out of memory!\n");
- return 1;
- }
- msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size);
- memset(flashchip_contents, 0xff, emu_chip_size);
-
- emu_persistent_image = extract_programmer_param("image");
- if (!emu_persistent_image) {
- /* Nothing else to do. */
- return 0;
- }
- if (!stat(emu_persistent_image, &image_stat)) {
- msg_pdbg("Found persistent image %s, size %li ",
- emu_persistent_image, (long)image_stat.st_size);
- if (image_stat.st_size == emu_chip_size) {
- msg_pdbg("matches.\n");
- msg_pdbg("Reading %s\n", emu_persistent_image);
- read_buf_from_file(flashchip_contents, emu_chip_size,
- emu_persistent_image);
- } else {
- msg_pdbg("doesn't match.\n");
- }
- }
-#endif
- return 0;
-}
-
int dummy_shutdown(void)
{
msg_pspew("%s\n", __func__);
@@ -512,3 +380,135 @@ int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int le
return spi_write_chunked(flash, buf, start, len,
spi_write_256_chunksize);
}
+
+int dummy_init(void)
+{
+ char *bustext = NULL;
+ char *tmp = NULL;
+#if EMULATE_CHIP
+ struct stat image_stat;
+#endif
+
+ msg_pspew("%s\n", __func__);
+
+ bustext = extract_programmer_param("bus");
+ msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default");
+ if (!bustext)
+ bustext = strdup("parallel+lpc+fwh+spi");
+ /* Convert the parameters to lowercase. */
+ tolower_string(bustext);
+
+ buses_supported = CHIP_BUSTYPE_NONE;
+ if (strstr(bustext, "parallel")) {
+ buses_supported |= CHIP_BUSTYPE_PARALLEL;
+ msg_pdbg("Enabling support for %s flash.\n", "parallel");
+ }
+ if (strstr(bustext, "lpc")) {
+ buses_supported |= CHIP_BUSTYPE_LPC;
+ msg_pdbg("Enabling support for %s flash.\n", "LPC");
+ }
+ if (strstr(bustext, "fwh")) {
+ buses_supported |= CHIP_BUSTYPE_FWH;
+ msg_pdbg("Enabling support for %s flash.\n", "FWH");
+ }
+ if (strstr(bustext, "spi")) {
+ buses_supported |= CHIP_BUSTYPE_SPI;
+ spi_controller = SPI_CONTROLLER_DUMMY;
+ msg_pdbg("Enabling support for %s flash.\n", "SPI");
+ }
+ if (buses_supported == CHIP_BUSTYPE_NONE)
+ msg_pdbg("Support for all flash bus types disabled.\n");
+ free(bustext);
+
+ tmp = extract_programmer_param("spi_write_256_chunksize");
+ if (tmp) {
+ spi_write_256_chunksize = atoi(tmp);
+ free(tmp);
+ if (spi_write_256_chunksize < 1) {
+ msg_perr("invalid spi_write_256_chunksize\n");
+ return 1;
+ }
+ }
+
+#if EMULATE_CHIP
+ tmp = extract_programmer_param("emulate");
+ if (!tmp) {
+ msg_pdbg("Not emulating any flash chip.\n");
+ /* Nothing else to do. */
+ return 0;
+ }
+#if EMULATE_SPI_CHIP
+ if (!strcmp(tmp, "M25P10.RES")) {
+ emu_chip = EMULATE_ST_M25P10_RES;
+ emu_chip_size = 128 * 1024;
+ emu_max_byteprogram_size = 128;
+ emu_max_aai_size = 0;
+ emu_jedec_se_size = 0;
+ emu_jedec_be_52_size = 0;
+ emu_jedec_be_d8_size = 32 * 1024;
+ emu_jedec_ce_60_size = 0;
+ emu_jedec_ce_c7_size = emu_chip_size;
+ msg_pdbg("Emulating ST M25P10.RES SPI flash chip (RES, page "
+ "write)\n");
+ }
+ if (!strcmp(tmp, "SST25VF040.REMS")) {
+ emu_chip = EMULATE_SST_SST25VF040_REMS;
+ emu_chip_size = 512 * 1024;
+ emu_max_byteprogram_size = 1;
+ emu_max_aai_size = 0;
+ emu_jedec_se_size = 4 * 1024;
+ emu_jedec_be_52_size = 32 * 1024;
+ emu_jedec_be_d8_size = 0;
+ emu_jedec_ce_60_size = emu_chip_size;
+ emu_jedec_ce_c7_size = 0;
+ msg_pdbg("Emulating SST SST25VF040.REMS SPI flash chip (REMS, "
+ "byte write)\n");
+ }
+ if (!strcmp(tmp, "SST25VF032B")) {
+ emu_chip = EMULATE_SST_SST25VF032B;
+ emu_chip_size = 4 * 1024 * 1024;
+ emu_max_byteprogram_size = 1;
+ emu_max_aai_size = 2;
+ emu_jedec_se_size = 4 * 1024;
+ emu_jedec_be_52_size = 32 * 1024;
+ emu_jedec_be_d8_size = 64 * 1024;
+ emu_jedec_ce_60_size = emu_chip_size;
+ emu_jedec_ce_c7_size = emu_chip_size;
+ msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI "
+ "write)\n");
+ }
+#endif
+ if (emu_chip == EMULATE_NONE) {
+ msg_perr("Invalid chip specified for emulation: %s\n", tmp);
+ free(tmp);
+ return 1;
+ }
+ free(tmp);
+ flashchip_contents = malloc(emu_chip_size);
+ if (!flashchip_contents) {
+ msg_perr("Out of memory!\n");
+ return 1;
+ }
+ msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size);
+ memset(flashchip_contents, 0xff, emu_chip_size);
+
+ emu_persistent_image = extract_programmer_param("image");
+ if (!emu_persistent_image) {
+ /* Nothing else to do. */
+ return 0;
+ }
+ if (!stat(emu_persistent_image, &image_stat)) {
+ msg_pdbg("Found persistent image %s, size %li ",
+ emu_persistent_image, (long)image_stat.st_size);
+ if (image_stat.st_size == emu_chip_size) {
+ msg_pdbg("matches.\n");
+ msg_pdbg("Reading %s\n", emu_persistent_image);
+ read_buf_from_file(flashchip_contents, emu_chip_size,
+ emu_persistent_image);
+ } else {
+ msg_pdbg("doesn't match.\n");
+ }
+ }
+#endif
+ return 0;
+}
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 7ff1d81..4e0fc67 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -128,6 +128,91 @@ static int get_buf(struct ftdi_context *ftdic, const unsigned char *buf,
return 0;
}
+int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ struct ftdi_context *ftdic = &ftdic_context;
+ static unsigned char *buf = NULL;
+ /* failed is special. We use bitwise ops, but it is essentially bool. */
+ int i = 0, ret = 0, failed = 0;
+ int bufsize;
+ static int oldbufsize = 0;
+
+ if (writecnt > 65536 || readcnt > 65536)
+ return SPI_INVALID_LENGTH;
+
+ /* buf is not used for the response from the chip. */
+ bufsize = max(writecnt + 9, 260 + 9);
+ /* Never shrink. realloc() calls are expensive. */
+ if (bufsize > oldbufsize) {
+ buf = realloc(buf, bufsize);
+ if (!buf) {
+ msg_perr("Out of memory!\n");
+ exit(1);
+ }
+ oldbufsize = bufsize;
+ }
+
+ /*
+ * Minimize USB transfers by packing as many commands as possible
+ * together. If we're not expecting to read, we can assert CS#, write,
+ * and deassert CS# all in one shot. If reading, we do three separate
+ * operations.
+ */
+ msg_pspew("Assert CS#\n");
+ buf[i++] = SET_BITS_LOW;
+ buf[i++] = 0 & ~cs_bits; /* assertive */
+ buf[i++] = pindir;
+
+ if (writecnt) {
+ buf[i++] = 0x11;
+ buf[i++] = (writecnt - 1) & 0xff;
+ buf[i++] = ((writecnt - 1) >> 8) & 0xff;
+ memcpy(buf + i, writearr, writecnt);
+ i += writecnt;
+ }
+
+ /*
+ * Optionally terminate this batch of commands with a
+ * read command, then do the fetch of the results.
+ */
+ if (readcnt) {
+ buf[i++] = 0x20;
+ buf[i++] = (readcnt - 1) & 0xff;
+ buf[i++] = ((readcnt - 1) >> 8) & 0xff;
+ ret = send_buf(ftdic, buf, i);
+ failed = ret;
+ /* We can't abort here, we still have to deassert CS#. */
+ if (ret)
+ msg_perr("send_buf failed before read: %i\n",
+ ret);
+ i = 0;
+ if (ret == 0) {
+ /*
+ * FIXME: This is unreliable. There's no guarantee that
+ * we read the response directly after sending the read
+ * command. We may be scheduled out etc.
+ */
+ ret = get_buf(ftdic, readarr, readcnt);
+ failed |= ret;
+ /* We can't abort here either. */
+ if (ret)
+ msg_perr("get_buf failed: %i\n", ret);
+ }
+ }
+
+ msg_pspew("De-assert CS#\n");
+ buf[i++] = SET_BITS_LOW;
+ buf[i++] = cs_bits;
+ buf[i++] = pindir;
+ ret = send_buf(ftdic, buf, i);
+ failed |= ret;
+ if (ret)
+ msg_perr("send_buf failed at end: %i\n", ret);
+
+ return failed ? -1 : 0;
+}
+
int ft2232_spi_init(void)
{
int f;
@@ -267,91 +352,6 @@ int ft2232_spi_init(void)
return 0;
}
-int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- struct ftdi_context *ftdic = &ftdic_context;
- static unsigned char *buf = NULL;
- /* failed is special. We use bitwise ops, but it is essentially bool. */
- int i = 0, ret = 0, failed = 0;
- int bufsize;
- static int oldbufsize = 0;
-
- if (writecnt > 65536 || readcnt > 65536)
- return SPI_INVALID_LENGTH;
-
- /* buf is not used for the response from the chip. */
- bufsize = max(writecnt + 9, 260 + 9);
- /* Never shrink. realloc() calls are expensive. */
- if (bufsize > oldbufsize) {
- buf = realloc(buf, bufsize);
- if (!buf) {
- msg_perr("Out of memory!\n");
- exit(1);
- }
- oldbufsize = bufsize;
- }
-
- /*
- * Minimize USB transfers by packing as many commands as possible
- * together. If we're not expecting to read, we can assert CS#, write,
- * and deassert CS# all in one shot. If reading, we do three separate
- * operations.
- */
- msg_pspew("Assert CS#\n");
- buf[i++] = SET_BITS_LOW;
- buf[i++] = 0 & ~cs_bits; /* assertive */
- buf[i++] = pindir;
-
- if (writecnt) {
- buf[i++] = 0x11;
- buf[i++] = (writecnt - 1) & 0xff;
- buf[i++] = ((writecnt - 1) >> 8) & 0xff;
- memcpy(buf + i, writearr, writecnt);
- i += writecnt;
- }
-
- /*
- * Optionally terminate this batch of commands with a
- * read command, then do the fetch of the results.
- */
- if (readcnt) {
- buf[i++] = 0x20;
- buf[i++] = (readcnt - 1) & 0xff;
- buf[i++] = ((readcnt - 1) >> 8) & 0xff;
- ret = send_buf(ftdic, buf, i);
- failed = ret;
- /* We can't abort here, we still have to deassert CS#. */
- if (ret)
- msg_perr("send_buf failed before read: %i\n",
- ret);
- i = 0;
- if (ret == 0) {
- /*
- * FIXME: This is unreliable. There's no guarantee that
- * we read the response directly after sending the read
- * command. We may be scheduled out etc.
- */
- ret = get_buf(ftdic, readarr, readcnt);
- failed |= ret;
- /* We can't abort here either. */
- if (ret)
- msg_perr("get_buf failed: %i\n", ret);
- }
- }
-
- msg_pspew("De-assert CS#\n");
- buf[i++] = SET_BITS_LOW;
- buf[i++] = cs_bits;
- buf[i++] = pindir;
- ret = send_buf(ftdic, buf, i);
- failed |= ret;
- if (ret)
- msg_perr("send_buf failed at end: %i\n", ret);
-
- return failed ? -1 : 0;
-}
-
void print_supported_usbdevs(const struct usbdev_status *devs)
{
int i;
diff --git a/it85spi.c b/it85spi.c
index a388d10..11a2ff5 100644
--- a/it85spi.c
+++ b/it85spi.c
@@ -226,6 +226,57 @@ void it85xx_exit_scratch_rom()
#endif
}
+/* According to ITE 8502 document, the procedure to follow mode is following:
+ * 1. write 0x00 to LPC/FWH address 0xffff_fexxh (drive CE# high)
+ * 2. write data to LPC/FWH address 0xffff_fdxxh (drive CE# low and MOSI
+ * with data)
+ * 3. read date from LPC/FWH address 0xffff_fdxxh (drive CE# low and get
+ * data from MISO)
+ */
+int it85xx_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ int i;
+
+ it85xx_enter_scratch_rom();
+ /* exit scratch rom ONLY when programmer shuts down. Otherwise, the
+ * temporary flash state may halt EC. */
+
+#ifdef LPC_IO
+ INDIRECT_A1(shm_io_base, (((unsigned long int)ce_high) >> 8) & 0xff);
+ INDIRECT_WRITE(shm_io_base, 0xFF); /* Write anything to this address.*/
+ INDIRECT_A1(shm_io_base, (((unsigned long int)ce_low) >> 8) & 0xff);
+#endif
+#ifdef LPC_MEMORY
+ mmio_writeb(0, ce_high);
+#endif
+ for (i = 0; i < writecnt; ++i) {
+#ifdef LPC_IO
+ INDIRECT_WRITE(shm_io_base, writearr[i]);
+#endif
+#ifdef LPC_MEMORY
+ mmio_writeb(writearr[i], ce_low);
+#endif
+ }
+ for (i = 0; i < readcnt; ++i) {
+#ifdef LPC_IO
+ readarr[i] = INDIRECT_READ(shm_io_base);
+#endif
+#ifdef LPC_MEMORY
+ readarr[i] = mmio_readb(ce_low);
+#endif
+ }
+#ifdef LPC_IO
+ INDIRECT_A1(shm_io_base, (((unsigned long int)ce_high) >> 8) & 0xff);
+ INDIRECT_WRITE(shm_io_base, 0xFF); /* Write anything to this address.*/
+#endif
+#ifdef LPC_MEMORY
+ mmio_writeb(0, ce_high);
+#endif
+
+ return 0;
+}
+
static int it85xx_spi_common_init(struct superio s)
{
chipaddr base;
@@ -295,56 +346,4 @@ int it85xx_shutdown(void)
it85xx_exit_scratch_rom();
return 0;
}
-
-/* According to ITE 8502 document, the procedure to follow mode is following:
- * 1. write 0x00 to LPC/FWH address 0xffff_fexxh (drive CE# high)
- * 2. write data to LPC/FWH address 0xffff_fdxxh (drive CE# low and MOSI
- * with data)
- * 3. read date from LPC/FWH address 0xffff_fdxxh (drive CE# low and get
- * data from MISO)
- */
-int it85xx_spi_send_command(unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- int i;
-
- it85xx_enter_scratch_rom();
- /* exit scratch rom ONLY when programmer shuts down. Otherwise, the
- * temporary flash state may halt EC. */
-
-#ifdef LPC_IO
- INDIRECT_A1(shm_io_base, (((unsigned long int)ce_high) >> 8) & 0xff);
- INDIRECT_WRITE(shm_io_base, 0xFF); /* Write anything to this address.*/
- INDIRECT_A1(shm_io_base, (((unsigned long int)ce_low) >> 8) & 0xff);
-#endif
-#ifdef LPC_MEMORY
- mmio_writeb(0, ce_high);
-#endif
- for (i = 0; i < writecnt; ++i) {
-#ifdef LPC_IO
- INDIRECT_WRITE(shm_io_base, writearr[i]);
-#endif
-#ifdef LPC_MEMORY
- mmio_writeb(writearr[i], ce_low);
-#endif
- }
- for (i = 0; i < readcnt; ++i) {
-#ifdef LPC_IO
- readarr[i] = INDIRECT_READ(shm_io_base);
-#endif
-#ifdef LPC_MEMORY
- readarr[i] = mmio_readb(ce_low);
-#endif
- }
-#ifdef LPC_IO
- INDIRECT_A1(shm_io_base, (((unsigned long int)ce_high) >> 8) & 0xff);
- INDIRECT_WRITE(shm_io_base, 0xFF); /* Write anything to this address.*/
-#endif
-#ifdef LPC_MEMORY
- mmio_writeb(0, ce_high);
-#endif
-
- return 0;
-}
-
#endif
diff --git a/it87spi.c b/it87spi.c
index 2b09d64..fdf6ccb 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -104,127 +104,6 @@ void probe_superio_ite(void)
return;
}
-static uint16_t it87spi_probe(uint16_t port)
-{
- uint8_t tmp = 0;
- char *portpos = NULL;
- uint16_t flashport = 0;
-
- enter_conf_mode_ite(port);
- /* NOLDN, reg 0x24, mask out lowest bit (suspend) */
- tmp = sio_read(port, 0x24) & 0xFE;
- /* If IT87SPI was not explicitly selected, we want to check
- * quickly if LPC->SPI translation is active.
- */
- if ((programmer == PROGRAMMER_INTERNAL) && !(tmp & (0x0E))) {
- msg_pdbg("No IT87* serial flash segment enabled.\n");
- exit_conf_mode_ite(port);
- /* Nothing to do. */
- return 0;
- }
- msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
- 0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis");
- msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
- 0x000E0000, 0x000FFFFF, (tmp & 1 << 1) ? "en" : "dis");
- msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
- 0xFFEE0000, 0xFFEFFFFF, (tmp & 1 << 2) ? "en" : "dis");
- msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
- 0xFFF80000, 0xFFFEFFFF, (tmp & 1 << 3) ? "en" : "dis");
- msg_pdbg("LPC write to serial flash %sabled\n",
- (tmp & 1 << 4) ? "en" : "dis");
- /* The LPC->SPI force write enable below only makes sense for
- * non-programmer mode.
- */
- /* If any serial flash segment is enabled, enable writing. */
- if ((tmp & 0xe) && (!(tmp & 1 << 4))) {
- msg_pdbg("Enabling LPC write to serial flash\n");
- tmp |= 1 << 4;
- sio_write(port, 0x24, tmp);
- }
- msg_pdbg("Serial flash pin %i\n", (tmp & 1 << 5) ? 87 : 29);
- /* LDN 0x7, reg 0x64/0x65 */
- sio_write(port, 0x07, 0x7);
- flashport = sio_read(port, 0x64) << 8;
- flashport |= sio_read(port, 0x65);
- msg_pdbg("Serial flash port 0x%04x\n", flashport);
- /* Non-default port requested? */
- portpos = extract_programmer_param("it87spiport");
- if (portpos) {
- char *endptr = NULL;
- unsigned long forced_flashport;
- forced_flashport = strtoul(portpos, &endptr, 0);
- /* Port 0, port >0x1000, unaligned ports and garbage strings
- * are rejected.
- */
- if (!forced_flashport || (forced_flashport >= 0x1000) ||
- (forced_flashport & 0x7) || (*endptr != '\0')) {
- /* Using ports below 0x100 is a really bad idea, and
- * should only be done if no port between 0x100 and
- * 0xff8 works due to routing issues.
- */
- msg_perr("Error: it87spiport specified, but no valid "
- "port specified.\nPort must be a multiple of "
- "0x8 and lie between 0x100 and 0xff8.\n");
- free(portpos);
- return 1;
- } else {
- flashport = (uint16_t)forced_flashport;
- msg_pinfo("Forcing serial flash port 0x%04x\n",
- flashport);
- sio_write(port, 0x64, (flashport >> 8));
- sio_write(port, 0x65, (flashport & 0xff));
- }
- }
- free(portpos);
- exit_conf_mode_ite(port);
- it8716f_flashport = flashport;
- if (buses_supported & CHIP_BUSTYPE_SPI)
- msg_pdbg("Overriding chipset SPI with IT87 SPI.\n");
- spi_controller = SPI_CONTROLLER_IT87XX;
- /* FIXME: Add the SPI bus or replace the other buses with it? */
- buses_supported |= CHIP_BUSTYPE_SPI;
- return 0;
-}
-
-int init_superio_ite(void)
-{
- int i;
- int ret = 0;
-
- for (i = 0; i < superio_count; i++) {
- if (superios[i].vendor != SUPERIO_VENDOR_ITE)
- continue;
-
- switch (superios[i].model) {
- case 0x8500:
- case 0x8502:
- case 0x8510:
- case 0x8511:
- case 0x8512:
- /* FIXME: This should be enabled, but we need a check
- * for laptop whitelisting due to the amount of things
- * which can go wrong if the EC firmware does not
- * implement the interface we want.
- */
- //it85xx_spi_init(superios[i]);
- break;
- case 0x8705:
- ret |= it8705f_write_enable(superios[i].port);
- break;
- case 0x8716:
- case 0x8718:
- case 0x8720:
- ret |= it87spi_probe(superios[i].port);
- break;
- default:
- msg_pdbg("Super I/O ID 0x%04hx is not on the list of "
- "flash capable controllers.\n",
- superios[i].model);
- }
- }
- return ret;
-}
-
/*
* The IT8716F only supports commands with length 1,2,4,5 bytes including
* command byte and can not read more than 3 bytes from the device.
@@ -386,4 +265,125 @@ int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf, int start,
return 0;
}
+static uint16_t it87spi_probe(uint16_t port)
+{
+ uint8_t tmp = 0;
+ char *portpos = NULL;
+ uint16_t flashport = 0;
+
+ enter_conf_mode_ite(port);
+ /* NOLDN, reg 0x24, mask out lowest bit (suspend) */
+ tmp = sio_read(port, 0x24) & 0xFE;
+ /* If IT87SPI was not explicitly selected, we want to check
+ * quickly if LPC->SPI translation is active.
+ */
+ if ((programmer == PROGRAMMER_INTERNAL) && !(tmp & (0x0E))) {
+ msg_pdbg("No IT87* serial flash segment enabled.\n");
+ exit_conf_mode_ite(port);
+ /* Nothing to do. */
+ return 0;
+ }
+ msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
+ 0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis");
+ msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
+ 0x000E0000, 0x000FFFFF, (tmp & 1 << 1) ? "en" : "dis");
+ msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
+ 0xFFEE0000, 0xFFEFFFFF, (tmp & 1 << 2) ? "en" : "dis");
+ msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n",
+ 0xFFF80000, 0xFFFEFFFF, (tmp & 1 << 3) ? "en" : "dis");
+ msg_pdbg("LPC write to serial flash %sabled\n",
+ (tmp & 1 << 4) ? "en" : "dis");
+ /* The LPC->SPI force write enable below only makes sense for
+ * non-programmer mode.
+ */
+ /* If any serial flash segment is enabled, enable writing. */
+ if ((tmp & 0xe) && (!(tmp & 1 << 4))) {
+ msg_pdbg("Enabling LPC write to serial flash\n");
+ tmp |= 1 << 4;
+ sio_write(port, 0x24, tmp);
+ }
+ msg_pdbg("Serial flash pin %i\n", (tmp & 1 << 5) ? 87 : 29);
+ /* LDN 0x7, reg 0x64/0x65 */
+ sio_write(port, 0x07, 0x7);
+ flashport = sio_read(port, 0x64) << 8;
+ flashport |= sio_read(port, 0x65);
+ msg_pdbg("Serial flash port 0x%04x\n", flashport);
+ /* Non-default port requested? */
+ portpos = extract_programmer_param("it87spiport");
+ if (portpos) {
+ char *endptr = NULL;
+ unsigned long forced_flashport;
+ forced_flashport = strtoul(portpos, &endptr, 0);
+ /* Port 0, port >0x1000, unaligned ports and garbage strings
+ * are rejected.
+ */
+ if (!forced_flashport || (forced_flashport >= 0x1000) ||
+ (forced_flashport & 0x7) || (*endptr != '\0')) {
+ /* Using ports below 0x100 is a really bad idea, and
+ * should only be done if no port between 0x100 and
+ * 0xff8 works due to routing issues.
+ */
+ msg_perr("Error: it87spiport specified, but no valid "
+ "port specified.\nPort must be a multiple of "
+ "0x8 and lie between 0x100 and 0xff8.\n");
+ free(portpos);
+ return 1;
+ } else {
+ flashport = (uint16_t)forced_flashport;
+ msg_pinfo("Forcing serial flash port 0x%04x\n",
+ flashport);
+ sio_write(port, 0x64, (flashport >> 8));
+ sio_write(port, 0x65, (flashport & 0xff));
+ }
+ }
+ free(portpos);
+ exit_conf_mode_ite(port);
+ it8716f_flashport = flashport;
+ if (buses_supported & CHIP_BUSTYPE_SPI)
+ msg_pdbg("Overriding chipset SPI with IT87 SPI.\n");
+ spi_controller = SPI_CONTROLLER_IT87XX;
+ /* FIXME: Add the SPI bus or replace the other buses with it? */
+ buses_supported |= CHIP_BUSTYPE_SPI;
+ return 0;
+}
+
+int init_superio_ite(void)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < superio_count; i++) {
+ if (superios[i].vendor != SUPERIO_VENDOR_ITE)
+ continue;
+
+ switch (superios[i].model) {
+ case 0x8500:
+ case 0x8502:
+ case 0x8510:
+ case 0x8511:
+ case 0x8512:
+ /* FIXME: This should be enabled, but we need a check
+ * for laptop whitelisting due to the amount of things
+ * which can go wrong if the EC firmware does not
+ * implement the interface we want.
+ */
+ //it85xx_spi_init(superios[i]);
+ break;
+ case 0x8705:
+ ret |= it8705f_write_enable(superios[i].port);
+ break;
+ case 0x8716:
+ case 0x8718:
+ case 0x8720:
+ ret |= it87spi_probe(superios[i].port);
+ break;
+ default:
+ msg_pdbg("Super I/O ID 0x%04hx is not on the list of "
+ "flash capable controllers.\n",
+ superios[i].model);
+ }
+ }
+ return ret;
+}
+
#endif
diff --git a/wbsio_spi.c b/wbsio_spi.c
index acf9cb2..12c458e 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -30,53 +30,6 @@
static uint16_t wbsio_spibase = 0;
-static uint16_t wbsio_get_spibase(uint16_t port)
-{
- uint8_t id;
- uint16_t flashport = 0;
-
- w836xx_ext_enter(port);
- id = sio_read(port, 0x20);
- if (id != 0xa0) {
- msg_perr("\nW83627 not found at 0x%x, id=0x%02x want=0xa0.\n", port, id);
- goto done;
- }
-
- if (0 == (sio_read(port, 0x24) & 2)) {
- msg_perr("\nW83627 found at 0x%x, but SPI pins are not enabled. (CR[0x24] bit 1=0)\n", port);
- goto done;
- }
-
- sio_write(port, 0x07, 0x06);
- if (0 == (sio_read(port, 0x30) & 1)) {
- msg_perr("\nW83627 found at 0x%x, but SPI is not enabled. (LDN6[0x30] bit 0=0)\n", port);
- goto done;
- }
-
- flashport = (sio_read(port, 0x62) << 8) | sio_read(port, 0x63);
-
-done:
- w836xx_ext_leave(port);
- return flashport;
-}
-
-int wbsio_check_for_spi(void)
-{
- if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT1)))
- if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT2)))
- return 1;
-
- msg_pspew("\nwbsio_spibase = 0x%x\n", wbsio_spibase);
-
- buses_supported |= CHIP_BUSTYPE_SPI;
- spi_controller = SPI_CONTROLLER_WBSIO;
- msg_pdbg("%s: Winbond saved on 4 register bits so max chip size is "
- "1024 KB!\n", __func__);
- max_rom_decode.spi = 1024 * 1024;
-
- return 0;
-}
-
/* W83627DHG has 11 command modes:
* 1=1 command only
* 2=1 command+1 data write
@@ -186,4 +139,51 @@ int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
return read_memmapped(flash, buf, start, len);
}
+static uint16_t wbsio_get_spibase(uint16_t port)
+{
+ uint8_t id;
+ uint16_t flashport = 0;
+
+ w836xx_ext_enter(port);
+ id = sio_read(port, 0x20);
+ if (id != 0xa0) {
+ msg_perr("\nW83627 not found at 0x%x, id=0x%02x want=0xa0.\n", port, id);
+ goto done;
+ }
+
+ if (0 == (sio_read(port, 0x24) & 2)) {
+ msg_perr("\nW83627 found at 0x%x, but SPI pins are not enabled. (CR[0x24] bit 1=0)\n", port);
+ goto done;
+ }
+
+ sio_write(port, 0x07, 0x06);
+ if (0 == (sio_read(port, 0x30) & 1)) {
+ msg_perr("\nW83627 found at 0x%x, but SPI is not enabled. (LDN6[0x30] bit 0=0)\n", port);
+ goto done;
+ }
+
+ flashport = (sio_read(port, 0x62) << 8) | sio_read(port, 0x63);
+
+done:
+ w836xx_ext_leave(port);
+ return flashport;
+}
+
+int wbsio_check_for_spi(void)
+{
+ if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT1)))
+ if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT2)))
+ return 1;
+
+ msg_pspew("\nwbsio_spibase = 0x%x\n", wbsio_spibase);
+
+ buses_supported |= CHIP_BUSTYPE_SPI;
+ spi_controller = SPI_CONTROLLER_WBSIO;
+ msg_pdbg("%s: Winbond saved on 4 register bits so max chip size is "
+ "1024 KB!\n", __func__);
+ max_rom_decode.spi = 1024 * 1024;
+
+ return 0;
+}
+
#endif
--
1.7.4.1
More information about the flashrom
mailing list