diff options
author | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2010-07-10 16:56:32 +0000 |
---|---|---|
committer | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2010-07-10 16:56:32 +0000 |
commit | 76d4b373ddbe191d621102c502aa4a9ab6c8bb25 (patch) | |
tree | dc504608f4210643a4a0c5d3280fc7342530678e /it87spi.c | |
parent | 2b6dcb36c4121ed12fa2fb66f133365bd88f2456 (diff) | |
download | flashrom-76d4b373ddbe191d621102c502aa4a9ab6c8bb25.tar.gz flashrom-76d4b373ddbe191d621102c502aa4a9ab6c8bb25.tar.bz2 flashrom-76d4b373ddbe191d621102c502aa4a9ab6c8bb25.zip |
Generify support for ITE IT8705 Super I/O
Autodetect the ITE IT8705 Super I/O and enable flash writes if it
performs LPC->Parallel translation. Remove board enables which triggered
the IT8705 write enable manually. Change the IT87 SPI special case to
cover IT87 LPC->SPI and LPC->Parallel translation.
Corresponding to flashrom svn r1073.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Tested on Syntax SV266A.
Acked-by: Paul Menzel <paulepanter@users.sourceforge.net>
Tested on Shuttle AK38N, all operations work fine.
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
Diffstat (limited to 'it87spi.c')
-rw-r--r-- | it87spi.c | 164 |
1 files changed, 85 insertions, 79 deletions
@@ -96,90 +96,109 @@ struct superio probe_superio_ite(void) return ret; } -static uint16_t find_ite_spi_flash_port(uint16_t port, uint16_t id) +static uint16_t it87spi_probe(uint16_t port) { uint8_t tmp = 0; char *portpos = NULL; uint16_t flashport = 0; - switch (id) { - case 0x8716: - case 0x8718: - case 0x8720: - 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); - break; - } - 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. + 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 1; + } + 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 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 && strlen(portpos)) { - flashport = strtol(portpos, (char **)NULL, 0); - msg_pinfo("Forcing serial flash port 0x%04x\n", - flashport); - sio_write(port, 0x64, (flashport >> 8)); - sio_write(port, 0x65, (flashport & 0xff)); - } else if (portpos) { - msg_perr("Error: it87spiport specified, but no port " - "given.\n"); + 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); /* FIXME: Return failure here once it87spi_common_init() * can handle the return value sanely. */ exit(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); - break; - /* TODO: Handle more IT87xx if they support flash translation */ - default: - msg_pdbg("SuperI/O ID %04hx is not on the controller list.\n", id); } - return flashport; + 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; + buses_supported |= CHIP_BUSTYPE_SPI; + return 0; } -int it87spi_common_init(void) +int init_superio_ite(void) { if (superio.vendor != SUPERIO_VENDOR_ITE) return 1; - it8716f_flashport = find_ite_spi_flash_port(superio.port, superio.model); - - if (it8716f_flashport) - spi_controller = SPI_CONTROLLER_IT87XX; - - return (!it8716f_flashport); + 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; } @@ -190,7 +209,7 @@ int it87spi_init(void) get_io_perms(); /* Probe for the Super I/O chip and fill global struct superio. */ probe_superio(); - ret = it87spi_common_init(); + ret = init_superio_ite(); if (!ret) { buses_supported = CHIP_BUSTYPE_SPI; } else { @@ -199,19 +218,6 @@ int it87spi_init(void) return ret; } -int it87xx_probe_spi_flash(const char *name) -{ - int ret; - - ret = it87spi_common_init(); - if (!ret) { - if (buses_supported & CHIP_BUSTYPE_SPI) - msg_pdbg("Overriding chipset SPI with IT87 SPI.\n"); - buses_supported |= CHIP_BUSTYPE_SPI; - } - 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. |