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>
diff --git a/it87spi.c b/it87spi.c
index eccee0e..3019729 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -96,90 +96,109 @@
 	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.
+	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 ((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.
-		 */
-		/* 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 @@
 	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 @@
 	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.