summaryrefslogtreecommitdiffstats
path: root/it87spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'it87spi.c')
-rw-r--r--it87spi.c164
1 files changed, 85 insertions, 79 deletions
diff --git a/it87spi.c b/it87spi.c
index eccee0e..3019729 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -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.
OpenPOWER on IntegriCloud