Introduce enable_flash_ich_fwh_decode()

ICH2 (and C-ICH)/3/4/5 also have FWH_SEL1/2 registers but at
different addresses. In preparation for implementing fwh_idsel
parsing for older ICH chipsets extract the parameter handling
and add variables for the offsets.

While FWH_DEC_EN1 is a 16bit register for ICH6, it is two separate
8bit registers on ICH5 and earlier. Implement all accesses with two
byte instructions instead, to prepare for extended support.

Corresponding to flashrom svn r1746.

Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
diff --git a/chipset_enable.c b/chipset_enable.c
index 3db7a8d..ee7963e 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -325,14 +325,21 @@
 	return enable_flash_ich(dev, name, 0x4e);
 }
 
-static int enable_flash_ich_dc(struct pci_dev *dev, const char *name)
+static int enable_flash_ich_fwh_decode(struct pci_dev *dev, const char *name)
 {
 	uint32_t fwh_conf;
+	uint8_t fwh_sel1, fwh_sel2, fwh_dec_en_lo, fwh_dec_en_hi;
 	int i, tmp;
 	char *idsel = NULL;
 	int max_decode_fwh_idsel = 0, max_decode_fwh_decode = 0;
 	int contiguous = 1;
 
+	/* Register map from ICH6 onwards. */
+	fwh_sel1 = 0xd0;
+	fwh_sel2 = 0xd4;
+	fwh_dec_en_lo = 0xd8;
+	fwh_dec_en_hi = 0xd9;
+
 	idsel = extract_programmer_param("fwh_idsel");
 	if (idsel && strlen(idsel)) {
 		uint64_t fwh_idsel_old, fwh_idsel;
@@ -349,14 +356,14 @@
 				 "unused bits set.\n");
 			goto idsel_garbage_out;
 		}
-		fwh_idsel_old = pci_read_long(dev, 0xd0);
+		fwh_idsel_old = pci_read_long(dev, fwh_sel1);
 		fwh_idsel_old <<= 16;
-		fwh_idsel_old |= pci_read_word(dev, 0xd4);
+		fwh_idsel_old |= pci_read_word(dev, fwh_sel2);
 		msg_pdbg("\nSetting IDSEL from 0x%012" PRIx64 " to "
 			 "0x%012" PRIx64 " for top 16 MB.", fwh_idsel_old,
 			 fwh_idsel);
-		rpci_write_long(dev, 0xd0, (fwh_idsel >> 16) & 0xffffffff);
-		rpci_write_word(dev, 0xd4, fwh_idsel & 0xffff);
+		rpci_write_long(dev, fwh_sel1, (fwh_idsel >> 16) & 0xffffffff);
+		rpci_write_word(dev, fwh_sel2, fwh_idsel & 0xffff);
 		/* FIXME: Decode settings are not changed. */
 	} else if (idsel) {
 		msg_perr("Error: fwh_idsel= specified, but no value given.\n");
@@ -372,7 +379,7 @@
 	 * have to be adjusted.
 	 */
 	/* FWH_SEL1 */
-	fwh_conf = pci_read_long(dev, 0xd0);
+	fwh_conf = pci_read_long(dev, fwh_sel1);
 	for (i = 7; i >= 0; i--) {
 		tmp = (fwh_conf >> (i * 4)) & 0xf;
 		msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x",
@@ -386,7 +393,7 @@
 		}
 	}
 	/* FWH_SEL2 */
-	fwh_conf = pci_read_word(dev, 0xd4);
+	fwh_conf = pci_read_word(dev, fwh_sel2);
 	for (i = 3; i >= 0; i--) {
 		tmp = (fwh_conf >> (i * 4)) & 0xf;
 		msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x",
@@ -401,7 +408,9 @@
 	}
 	contiguous = 1;
 	/* FWH_DEC_EN1 */
-	fwh_conf = pci_read_word(dev, 0xd8);
+	fwh_conf = pci_read_byte(dev, fwh_dec_en_hi);
+	fwh_conf <<= 8;
+	fwh_conf |= pci_read_byte(dev, fwh_dec_en_lo);
 	for (i = 7; i >= 0; i--) {
 		tmp = (fwh_conf >> (i + 0x8)) & 0x1;
 		msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled",
@@ -429,6 +438,17 @@
 	max_rom_decode.fwh = min(max_decode_fwh_idsel, max_decode_fwh_decode);
 	msg_pdbg("\nMaximum FWH chip size: 0x%x bytes", max_rom_decode.fwh);
 
+	return 0;
+}
+
+static int enable_flash_ich_dc(struct pci_dev *dev, const char *name)
+{
+	int err;
+
+	/* Configure FWH IDSEL decoder maps. */
+	if ((err = enable_flash_ich_fwh_decode(dev, name)) != 0)
+		return err;
+
 	/* If we're called by enable_flash_ich_dc_spi, it will override
 	 * internal_buses_supported anyway.
 	 */