Author: stefanct Date: Sat Aug 24 14:18:17 2013 New Revision: 1720 URL: http://flashrom.org/trac/flashrom/changeset/1720
Log: IT87: Add ability to select between chips on GIGABYTE DualBIOS boards.
Thanks to Vadim Girlin for finding out how to do that. This is known to work on GA-MA770-UD3, GA-B75M-D3V, GA-B75N and GA-H61M-S1 (only M_BIOS is populated).
Signed-off-by: Vadim Girlin vadimgirlin@gmail.com Signed-off-by: Damien Zammit damien@zamaudio.com Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at Tested-by: Damien Zammit damien@zamaudio.com Tested-by: Anton Kochkov anton.kochkov@gmail.com Acked-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at
Modified: trunk/flashrom.8 trunk/internal.c trunk/it87spi.c
Modified: trunk/flashrom.8 ============================================================================== --- trunk/flashrom.8 Sat Aug 24 04:10:18 2013 (r1719) +++ trunk/flashrom.8 Sat Aug 24 14:18:17 2013 (r1720) @@ -315,6 +315,19 @@ .TP .B ITE IT87 Super I/O .sp +If your mainboard is manufactured by GIGABYTE and supports DualBIOS it is very likely that it uses an +ITE IT87 series Super I/O to switch between the two flash chips. Only one of them can be accessed at a time +and you can manually select which one to use with the +.sp +.B " flashrom -p internal:dualbiosindex=chip" +.sp +syntax where +.B chip +is the index of the chip to use (0 = main, 1 = backup). You can check which one is currently selected by +leaving out the +.B chip +parameter. +.sp If your mainboard uses an ITE IT87 series Super I/O for LPC<->SPI flash bus translation, flashrom should autodetect that configuration. If you want to set the I/O base port of the IT87 series SPI controller manually instead of
Modified: trunk/internal.c ============================================================================== --- trunk/internal.c Sat Aug 24 04:10:18 2013 (r1719) +++ trunk/internal.c Sat Aug 24 14:18:17 2013 (r1720) @@ -331,9 +331,8 @@ return ret;
#if defined(__i386__) || defined(__x86_64__) - /* Probe unconditionally for IT87* LPC->SPI translation and for - * IT87* Parallel write enable. - */ + /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and + * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */ init_superio_ite(); #endif
Modified: trunk/it87spi.c ============================================================================== --- trunk/it87spi.c Sat Aug 24 04:10:18 2013 (r1719) +++ trunk/it87spi.c Sat Aug 24 14:18:17 2013 (r1720) @@ -27,6 +27,7 @@
#include <string.h> #include <stdlib.h> +#include <errno.h> #include "flash.h" #include "chipdrivers.h" #include "programmer.h" @@ -36,7 +37,7 @@ #define ITE_SUPERIO_PORT1 0x2e #define ITE_SUPERIO_PORT2 0x4e
-uint16_t it8716f_flashport = 0; +static uint16_t it8716f_flashport = 0; /* use fast 33MHz SPI (<>0) or slow 16MHz (0) */ static int fast_spi = 1;
@@ -124,10 +125,40 @@ static uint16_t it87spi_probe(uint16_t port) { uint8_t tmp = 0; - char *portpos = NULL; uint16_t flashport = 0;
enter_conf_mode_ite(port); + + char *param = extract_programmer_param("dualbiosindex"); + if (param != NULL) { + sio_write(port, 0x07, 0x07); /* Select GPIO LDN */ + tmp = sio_read(port, 0xEF); + if (*param == '\0') { /* Print current setting only. */ + free(param); + } else { + char *dualbiosindex_suffix; + errno = 0; + long chip_index = strtol(param, &dualbiosindex_suffix, 0); + free(param); + if (errno != 0 || *dualbiosindex_suffix != '\0' || chip_index < 0 || chip_index > 1) { + msg_perr("DualBIOS: Invalid chip index requested - choose 0 or 1.\n"); + exit_conf_mode_ite(port); + return 1; + } + if (chip_index != (tmp & 1)) { + msg_pdbg("DualBIOS: Previous chip index: %d\n", tmp & 1); + sio_write(port, 0xEF, (tmp & 0xFE) | chip_index); + tmp = sio_read(port, 0xEF); + if ((tmp & 1) != chip_index) { + msg_perr("DualBIOS: Chip selection failed.\n"); + exit_conf_mode_ite(port); + return 1; + } + } + } + msg_pinfo("DualBIOS: Selected chip: %d\n", tmp & 1); + } + /* NOLDN, reg 0x24, mask out lowest bit (suspend) */ tmp = sio_read(port, 0x24) & 0xFE; /* Check if LPC->SPI translation is active. */ @@ -163,11 +194,11 @@ 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) { + param = extract_programmer_param("it87spiport"); + if (param) { char *endptr = NULL; unsigned long forced_flashport; - forced_flashport = strtoul(portpos, &endptr, 0); + forced_flashport = strtoul(param, &endptr, 0); /* Port 0, port >0x1000, unaligned ports and garbage strings * are rejected. */ @@ -180,7 +211,8 @@ 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); + exit_conf_mode_ite(port); + free(param); return 1; } else { flashport = (uint16_t)forced_flashport; @@ -190,7 +222,7 @@ sio_write(port, 0x65, (flashport & 0xff)); } } - free(portpos); + free(param); exit_conf_mode_ite(port); it8716f_flashport = flashport; if (internal_buses_supported & BUS_SPI) @@ -228,6 +260,7 @@ case 0x8716: case 0x8718: case 0x8720: + case 0x8728: ret |= it87spi_probe(superios[i].port); break; default: