Commit 4dd0f906 authored by Vadim Girlin's avatar Vadim Girlin Committed by Stefan Tauner
Browse files

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).

Corresponding to flashrom svn r1720.
Signed-off-by: default avatarVadim Girlin <vadimgirlin@gmail.com>
Signed-off-by: default avatarDamien Zammit <damien@zamaudio.com>
Signed-off-by: default avatarStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Tested-by: default avatarDamien Zammit <damien@zamaudio.com>
Tested-by: default avatarAnton Kochkov <anton.kochkov@gmail.com>
Acked-by: default avatarStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
parent bdead0d2
...@@ -315,6 +315,19 @@ do not match, it will refuse to write the image unless you specify ...@@ -315,6 +315,19 @@ do not match, it will refuse to write the image unless you specify
.TP .TP
.B ITE IT87 Super I/O .B ITE IT87 Super I/O
.sp .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 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 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 set the I/O base port of the IT87 series SPI controller manually instead of
......
...@@ -331,9 +331,8 @@ int internal_init(void) ...@@ -331,9 +331,8 @@ int internal_init(void)
return ret; return ret;
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
/* Probe unconditionally for IT87* LPC->SPI translation and for /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
* IT87* Parallel write enable. * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
*/
init_superio_ite(); init_superio_ite();
#endif #endif
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include "flash.h" #include "flash.h"
#include "chipdrivers.h" #include "chipdrivers.h"
#include "programmer.h" #include "programmer.h"
...@@ -36,7 +37,7 @@ ...@@ -36,7 +37,7 @@
#define ITE_SUPERIO_PORT1 0x2e #define ITE_SUPERIO_PORT1 0x2e
#define ITE_SUPERIO_PORT2 0x4e #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) */ /* use fast 33MHz SPI (<>0) or slow 16MHz (0) */
static int fast_spi = 1; static int fast_spi = 1;
...@@ -124,10 +125,40 @@ static const struct spi_programmer spi_programmer_it87xx = { ...@@ -124,10 +125,40 @@ static const struct spi_programmer spi_programmer_it87xx = {
static uint16_t it87spi_probe(uint16_t port) static uint16_t it87spi_probe(uint16_t port)
{ {
uint8_t tmp = 0; uint8_t tmp = 0;
char *portpos = NULL;
uint16_t flashport = 0; uint16_t flashport = 0;
enter_conf_mode_ite(port); 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) */ /* NOLDN, reg 0x24, mask out lowest bit (suspend) */
tmp = sio_read(port, 0x24) & 0xFE; tmp = sio_read(port, 0x24) & 0xFE;
/* Check if LPC->SPI translation is active. */ /* Check if LPC->SPI translation is active. */
...@@ -163,11 +194,11 @@ static uint16_t it87spi_probe(uint16_t port) ...@@ -163,11 +194,11 @@ static uint16_t it87spi_probe(uint16_t port)
flashport |= sio_read(port, 0x65); flashport |= sio_read(port, 0x65);
msg_pdbg("Serial flash port 0x%04x\n", flashport); msg_pdbg("Serial flash port 0x%04x\n", flashport);
/* Non-default port requested? */ /* Non-default port requested? */
portpos = extract_programmer_param("it87spiport"); param = extract_programmer_param("it87spiport");
if (portpos) { if (param) {
char *endptr = NULL; char *endptr = NULL;
unsigned long forced_flashport; 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 /* Port 0, port >0x1000, unaligned ports and garbage strings
* are rejected. * are rejected.
*/ */
...@@ -180,7 +211,8 @@ static uint16_t it87spi_probe(uint16_t port) ...@@ -180,7 +211,8 @@ static uint16_t it87spi_probe(uint16_t port)
msg_perr("Error: it87spiport specified, but no valid " msg_perr("Error: it87spiport specified, but no valid "
"port specified.\nPort must be a multiple of " "port specified.\nPort must be a multiple of "
"0x8 and lie between 0x100 and 0xff8.\n"); "0x8 and lie between 0x100 and 0xff8.\n");
free(portpos); exit_conf_mode_ite(port);
free(param);
return 1; return 1;
} else { } else {
flashport = (uint16_t)forced_flashport; flashport = (uint16_t)forced_flashport;
...@@ -190,7 +222,7 @@ static uint16_t it87spi_probe(uint16_t port) ...@@ -190,7 +222,7 @@ static uint16_t it87spi_probe(uint16_t port)
sio_write(port, 0x65, (flashport & 0xff)); sio_write(port, 0x65, (flashport & 0xff));
} }
} }
free(portpos); free(param);
exit_conf_mode_ite(port); exit_conf_mode_ite(port);
it8716f_flashport = flashport; it8716f_flashport = flashport;
if (internal_buses_supported & BUS_SPI) if (internal_buses_supported & BUS_SPI)
...@@ -228,6 +260,7 @@ int init_superio_ite(void) ...@@ -228,6 +260,7 @@ int init_superio_ite(void)
case 0x8716: case 0x8716:
case 0x8718: case 0x8718:
case 0x8720: case 0x8720:
case 0x8728:
ret |= it87spi_probe(superios[i].port); ret |= it87spi_probe(superios[i].port);
break; break;
default: default:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment