From bfecef6986b25b630605054680264daf09046f65 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Wed, 27 Apr 2011 14:34:08 +0000 Subject: 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 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 --- it85spi.c | 76 +++++++-------------------------------------------------------- 1 file changed, 8 insertions(+), 68 deletions(-) (limited to 'it85spi.c') diff --git a/it85spi.c b/it85spi.c index d122a18..1710d8e 100644 --- a/it85spi.c +++ b/it85spi.c @@ -47,9 +47,6 @@ /* Constants for Logical Device registers */ #define LDNSEL 0x07 -#define CHIP_ID_BYTE1_REG 0x20 -#define CHIP_ID_BYTE2_REG 0x21 -#define CHIP_CHIP_VER_REG 0x22 /* These are standard Super I/O 16-bit base address registers */ #define SHM_IO_BAR0 0x60 /* big-endian, this is high bits */ @@ -86,44 +83,6 @@ unsigned int shm_io_base; unsigned char *ce_high, *ce_low; static int it85xx_scratch_rom_reenter = 0; -uint16_t probe_id_ite85(uint16_t port) -{ - uint16_t id; - - id = sio_read(port, CHIP_ID_BYTE1_REG) << 8 | - sio_read(port, CHIP_ID_BYTE2_REG); - - return id; -} - -struct superio probe_superio_ite85xx(void) -{ - struct superio ret = {}; - uint16_t ite_ports[] = {ITE_SUPERIO_PORT1, ITE_SUPERIO_PORT2, 0}; - uint16_t *i = ite_ports; - - ret.vendor = SUPERIO_VENDOR_ITE; - for (; *i; i++) { - ret.port = *i; - ret.model = probe_id_ite85(ret.port); - switch (ret.model >> 8) { - case 0x85: - msg_pdbg("Found EC: ITE85xx (Vendor:0x%02x,ID:0x%02x," - "Rev:0x%02x) on sio_port:0x%x.\n", - ret.model >> 8, ret.model & 0xff, - sio_read(ret.port, CHIP_CHIP_VER_REG), - ret.port); - return ret; - } - } - - /* No good ID found. */ - ret.vendor = SUPERIO_VENDOR_NONE; - ret.port = 0; - ret.model = 0; - return ret; -} - /* This function will poll the keyboard status register until either * an expected value shows up, or * timeout reaches. @@ -267,20 +226,18 @@ void it85xx_exit_scratch_rom() #endif } -int it85xx_spi_common_init(void) +static int it85xx_spi_common_init(struct superio s) { chipaddr base; msg_pdbg("%s():%d superio.vendor=0x%02x\n", __func__, __LINE__, - superio.vendor); - if (superio.vendor != SUPERIO_VENDOR_ITE) - return 1; + s.vendor); #ifdef LPC_IO /* Get LPCPNP of SHM. That's big-endian */ - sio_write(superio.port, LDNSEL, 0x0F); /* Set LDN to SHM (0x0F) */ - shm_io_base = (sio_read(superio.port, SHM_IO_BAR0) << 8) + - sio_read(superio.port, SHM_IO_BAR1); + sio_write(s.port, LDNSEL, 0x0F); /* Set LDN to SHM (0x0F) */ + shm_io_base = (sio_read(s.port, SHM_IO_BAR0) << 8) + + sio_read(s.port, SHM_IO_BAR1); msg_pdbg("%s():%d shm_io_base=0x%04x\n", __func__, __LINE__, shm_io_base); @@ -311,25 +268,7 @@ int it85xx_spi_common_init(void) return 0; } -/* Called by programmer_entry .init */ -int it85xx_spi_init(void) -{ - int ret; - - get_io_perms(); - /* Probe for the Super I/O chip and fill global struct superio. */ - probe_superio(); - ret = it85xx_spi_common_init(); - if (!ret) { - buses_supported = CHIP_BUSTYPE_SPI; - } else { - buses_supported = CHIP_BUSTYPE_NONE; - } - return ret; -} - -/* Called by internal_init() */ -int it85xx_probe_spi_flash(void) +int it85xx_spi_init(struct superio s) { int ret; @@ -337,13 +276,14 @@ int it85xx_probe_spi_flash(void) msg_pdbg("%s():%d buses not support FWH\n", __func__, __LINE__); return 1; } - ret = it85xx_spi_common_init(); + ret = it85xx_spi_common_init(s); msg_pdbg("FWH: %s():%d ret=%d\n", __func__, __LINE__, ret); if (!ret) { msg_pdbg("%s():%d buses_supported=0x%x\n", __func__, __LINE__, buses_supported); if (buses_supported & CHIP_BUSTYPE_FWH) msg_pdbg("Overriding chipset SPI with IT85 FWH|SPI.\n"); + /* Really leave FWH enabled? */ buses_supported |= CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI; } return ret; -- cgit v1.1