diff options
author | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2011-04-27 14:34:08 +0000 |
---|---|---|
committer | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2011-04-27 14:34:08 +0000 |
commit | bfecef6986b25b630605054680264daf09046f65 (patch) | |
tree | a54fe83e5bd047ca0ae0af1469973a76acddceb8 /it87spi.c | |
parent | 880e867ae823dbbd140731f2eaa2ea656b4b9153 (diff) | |
download | flashrom-bfecef6986b25b630605054680264daf09046f65.tar.gz flashrom-bfecef6986b25b630605054680264daf09046f65.tar.bz2 flashrom-bfecef6986b25b630605054680264daf09046f65.zip |
Add support for more than one Super I/O or EC per machine
Flashrom currently only supports exactly one Super I/O or Embedded
Controller, and this means quite a few notebooks and a small subset of
desktop/server boards cannot be handled reliably and easily.
Allow detection and initialization of up to 3 Super I/O and/or EC chips.
WARNING! If a Super I/O or EC responds on multiple ports (0x2e and
0x4e), the code will do the wrong thing (namely, initialize the hardware
twice). I have no idea if we should handle such situations, and whether
we should ignore the second chip with identical ID or not. Initializing
the hardware twice for the IT87* family is _not_ a problem, but I don't
know how well IT85* can handle it (and whether IT85* would listen at
more than one port anyway).
Corresponding to flashrom svn r1289.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Thanks to Thomas Schneider for testing on a board with ITE IT87* SPI.
Test report (success) is here: http://paste.flashrom.org/view.php?id=379
Thanks to David Hendricks for testing on a Google Cr-48 laptop with
ITE IT85* EC SPI. Test report (success) is here:
http://www.flashrom.org/pipermail/flashrom/2011-April/006275.html
Acked-by: David Hendricks <dhendrix@google.com>
Diffstat (limited to 'it87spi.c')
-rw-r--r-- | it87spi.c | 121 |
1 files changed, 66 insertions, 55 deletions
@@ -42,6 +42,7 @@ static int fast_spi = 1; /* Helper functions for most recent ITE IT87xx Super I/O chips */ #define CHIP_ID_BYTE1_REG 0x20 #define CHIP_ID_BYTE2_REG 0x21 +#define CHIP_VER_REG 0x22 void enter_conf_mode_ite(uint16_t port) { OUTB(0x87, port); @@ -70,31 +71,37 @@ uint16_t probe_id_ite(uint16_t port) return id; } -struct superio probe_superio_ite(void) +void probe_superio_ite(void) { - struct superio ret = {}; + struct superio s = {}; uint16_t ite_ports[] = {ITE_SUPERIO_PORT1, ITE_SUPERIO_PORT2, 0}; uint16_t *i = ite_ports; - ret.vendor = SUPERIO_VENDOR_ITE; + s.vendor = SUPERIO_VENDOR_ITE; for (; *i; i++) { - ret.port = *i; - ret.model = probe_id_ite(ret.port); - switch (ret.model >> 8) { + s.port = *i; + s.model = probe_id_ite(s.port); + switch (s.model >> 8) { case 0x82: case 0x86: case 0x87: - msg_pinfo("Found ITE Super I/O, ID 0x%04hx.\n", - ret.model); - return ret; + /* FIXME: Print revision for all models? */ + msg_pdbg("Found ITE Super I/O, ID 0x%04hx on port " + "0x%x\n", s.model, s.port); + register_superio(s); + break; + case 0x85: + msg_pdbg("Found ITE EC, ID 0x%04hx," + "Rev 0x%02x on port 0x%x.\n", + s.model, + sio_read(s.port, CHIP_VER_REG), + s.port); + register_superio(s); + break; } } - /* No good ID found. */ - ret.vendor = SUPERIO_VENDOR_NONE; - ret.port = 0; - ret.model = 0; - return ret; + return; } static uint16_t it87spi_probe(uint16_t port) @@ -113,7 +120,7 @@ static uint16_t it87spi_probe(uint16_t port) msg_pdbg("No IT87* serial flash segment enabled.\n"); exit_conf_mode_ite(port); /* Nothing to do. */ - return 1; + return 0; } msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n", 0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis"); @@ -159,10 +166,7 @@ static uint16_t it87spi_probe(uint16_t port) "port specified.\nPort must be a multiple of " "0x8 and lie between 0x100 and 0xff8.\n"); free(portpos); - /* FIXME: Return failure here once it87spi_common_init() - * can handle the return value sanely. - */ - exit(1); + return 1; } else { flashport = (uint16_t)forced_flashport; msg_pinfo("Forcing serial flash port 0x%04x\n", @@ -177,44 +181,46 @@ static uint16_t it87spi_probe(uint16_t port) 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) { - if (superio.vendor != SUPERIO_VENDOR_ITE) - return 1; - - switch (superio.model) { - case 0x8705: - return it8705f_write_enable(superio.port); - break; - case 0x8716: - case 0x8718: - case 0x8720: - return it87spi_probe(superio.port); - break; - default: - msg_pdbg("Super I/O ID 0x%04hx is not on the list of flash " - "capable controllers.\n", superio.model); - } - return 1; -} - - -int it87spi_init(void) -{ - int ret; - - get_io_perms(); - /* Probe for the Super I/O chip and fill global struct superio. */ - probe_superio(); - ret = init_superio_ite(); - if (!ret) { - buses_supported = CHIP_BUSTYPE_SPI; - } else { - buses_supported = CHIP_BUSTYPE_NONE; + 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; } @@ -323,10 +329,13 @@ static int it8716f_spi_page_program(struct flashchip *flash, uint8_t *buf, int s */ int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len) { - int total_size = 1024 * flash->total_size; fast_spi = 0; - if ((programmer == PROGRAMMER_IT87SPI) || (total_size > 512 * 1024)) { + /* FIXME: Check if someone explicitly requested to use IT87 SPI although + * the mainboard does not use IT87 SPI translation. This should be done + * via a programmer parameter for the internal programmer. + */ + if ((flash->total_size * 1024 > 512 * 1024)) { spi_read_chunked(flash, buf, start, len, 3); } else { read_memmapped(flash, buf, start, len); @@ -343,9 +352,11 @@ int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf, int start, * so page_size > 256 bytes needs a fallback. * FIXME: Split too big page writes into chunks IT87* can handle instead * of degrading to single-byte program. + * FIXME: Check if someone explicitly requested to use IT87 SPI although + * the mainboard does not use IT87 SPI translation. This should be done + * via a programmer parameter for the internal programmer. */ - if ((programmer == PROGRAMMER_IT87SPI) || - (flash->total_size * 1024 > 512 * 1024) || + if ((flash->total_size * 1024 > 512 * 1024) || (flash->page_size > 256)) { spi_chip_write_1(flash, buf, start, len); } else { |