This is to prepare the SPI registration patch without needing to do forward declarations.
Signed-off-by: Michael Karcher flashrom@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