[flashrom] [PATCH] Boards: Unify all intel ICH GPIO raising.

Luc Verhaegen libv at skynet.be
Thu Oct 22 02:56:46 CEST 2009


Ok, big change here which will require several of the people on the list 
below to test and Ack this patch. But one has to admit; the result is 
worth it.

Jonathan, can you verify this patch on your acorp 6A815EPD (preferably 
also with the previous patch)? Thanks for having replied that swiftly 
last time :)

Uwe, it seems that the Asus P4B266 is yours, the code was committed as
r247. Can you send in an lspci -vvnnxxx to the list as well?

Carl-Daniel, the Dell is from your commit, r728. Any lspci on that?

David, i would guess that the MSI MS-7046 is your board (original 
commit r414), can you go and verify this code on this hardware? We would 
like to have an lspci -vvnnxxx for this board too.

Stepan, it seems that you committed the kontron 986LCD-M board enable. 
Can you check whether this code still works with your board, and can you 
also provide an lspci -vvnnxxx? I would also like to get rid of the 
entry which just matches one pci devices, and the coreboot ids in the 
table.

Richie, can you give this code a spin on your Abit IP35? (original 
commit r642)

Bojan? Asus P4P800-E seems to be yours and it was added just under two 
months ago in r682. Can you give this code a run too?

I would like to see at least 4 of these boards get an Ack before this 
can be committed.

Thanks all, now i can send in at least two more board enables which go 
on top of this stuff.

Luc Verhaegen.
-------------- next part --------------
Boards: Unify all intel ICH GPIO setting in one function.

Instead of scheme-like overgeneralising, we provide a function with
straightforward arguments. Apart from the notices in front of this
function, the code in there should be generally applicable to the
available ICH devices. A datasheet has been checked for each of the
major families.

A few boards have been moved around to sit below the ich_gpio_set
function and might make this patch a lot tougher to verify, but this
is not unovercomeable.

Signed-off-by: Luc Verhaegen <libv at skynet.be>

Index: board_enable.c
===================================================================
--- board_enable.c	(revision 752)
+++ board_enable.c	(working copy)
@@ -523,32 +523,6 @@
 }
 
 /**
- * Suited for Acorp 6A815EPD.
- */
-static int board_acorp_6a815epd(const char *name)
-{
-	struct pci_dev *dev;
-	uint16_t port;
-	uint8_t val;
-
-	dev = pci_dev_find(0x8086, 0x2440);	/* Intel ICH2 LPC */
-	if (!dev) {
-		fprintf(stderr, "\nERROR: ICH2 LPC bridge not found.\n");
-		return -1;
-	}
-
-	/* Use GPIOBASE register to find where the GPIO is mapped. */
-	port = (pci_read_word(dev, 0x58) & 0xFFC0) + 0xE;
-
-	val = INB(port);
-	val |= 0x80;		/* Top Block Lock -- pin 8 of PLCC32 */
-	val |= 0x40;		/* Lower Blocks Lock -- pin 7 of PLCC32 */
-	OUTB(val, port);
-
-	return 0;
-}
-
-/**
  * Suited for Artec Group DBE61 and DBE62.
  */
 static int board_artecgroup_dbe6x(const char *name)
@@ -590,104 +564,227 @@
 }
 
 /**
- * Set the specified GPIO on the specified ICHx southbridge to high.
+ * Raises a GPIO line on intel ICH, ICH0 and ICH2 through ICH10 southbridges.
  *
- * @param name The name of this board.
- * @param ich_vendor PCI vendor ID of the specified ICHx southbridge.
- * @param ich_device PCI device ID of the specified ICHx southbridge.
- * @param gpiobase_reg GPIOBASE register offset in the LPC bridge.
- * @param gp_lvl Offset of GP_LVL register in I/O space, relative to GPIOBASE.
- * @param gp_lvl_bitmask GP_LVL bitmask (set GPIO bits to 1, all others to 0).
- * @param gpio_bit The bit (GPIO) which shall be set to high.
- * @return If the write-enable was successful return 0, otherwise return -1.
+ * GPIO lines are not actually checked.
+ * More than 32 GPIO pins only become available with the ICH3.
+ * From ICH10, a third bank appears, but ICH10 only implements GPIO72.
  */
-static int ich_gpio_raise(const char *name, uint16_t ich_vendor,
-			  uint16_t ich_device, uint8_t gpiobase_reg,
-			  uint8_t gp_lvl, uint32_t gp_lvl_bitmask,
-			  unsigned int gpio_bit)
+static void ich_gpio_raise(struct pci_dev *dev, unsigned int gpio)
 {
+	uint16_t base;
+	uint32_t tmp;
+
+	/* get PM IO base */
+	switch (dev->device_id) {
+	case 0x2410: /* 82801AA (ICH) */
+	case 0x2420: /* 82801AB (ICH0) */
+	case 0x2440: /* 82801BA (ICH2) */
+	case 0x244C: /* 82801BAM (ICH2M) */
+	case 0x2450: /* 82801E (C-ICH) */
+	case 0x2480: /*	82801CA (ICH3-S) */
+	case 0x248C: /* 82801CAM (ICH3-M) */
+	case 0x24C0: /* 82801DB/DBL (ICH4/ICH4-L) */
+	case 0x24CC: /* 82801DBM (ICH4-M) */
+	case 0x24D0: /* 82801EB/ER (ICH5/ICH5R) */
+	case 0x24DC: /* 82801EB (ICH5) */
+		base = pci_read_long(dev, 0x58) & 0x0000FFC0;
+		break;
+	case 0x2640: /* 82801FB/FR (ICH6/ICH6R) */
+	case 0x2641: /* 82801FBM (ICH6M) */
+	case 0x2642: /* 82801FW/FRW (ICH6W/ICH6RW) */
+	case 0x27B0: /* 82801GH (ICH7DH) */
+	case 0x27B8: /* 82801GB/GR (ICH7 Family) */
+	case 0x27B9: /* 82801GBM (ICH7-M) */
+	case 0x27BD: /* 82801GHM (ICH7-M DH) */
+	case 0x2810: /* 82801HB/HR (ICH8/R) */
+	case 0x2811: /* 82801HBM (ICH8M-E) */
+	case 0x2812: /* 82801HH (ICH8DH) */
+	case 0x2814: /* 82801HO (ICH8DO) */
+	case 0x2815: /* 82801HEM (ICH8M) */
+	case 0x2912: /* 82801IH (ICH9DH) */
+	case 0x2914: /* 82801IO (ICH9DO) */
+	case 0x2916: /* 82801IR (ICH9R) */
+	case 0x2917: /* 82801IEM (ICH9M-E) */
+	case 0x2918: /* 82801IB (ICH9) */
+	case 0x2919: /* 82801IBM (ICH9M) */
+	case 0x3A14: /* 82801JDO (ICH10DO) */
+	case 0x3A16: /* 82801JIR (ICH10R) */
+	case 0x3A18: /* 82801JIB (ICH10) */
+	case 0x3A1A: /* 82801JD (ICH10D) */
+		base = pci_read_long(dev, 0x48) & 0x0000FFC0;
+		break;
+	default:
+		fprintf(stderr, "\nERROR: Unknown Intel ICH: 0x%04X.\n",
+			dev->device_id);
+		return;
+	}
+
+	if (gpio < 32) {
+		/* Set line to GPIO */
+		tmp = INL(base);
+		/* ICH/ICH0 multiplexes 27/28 on the line set. */
+		if ((gpio == 28) &&
+		    ((dev->device_id == 0x2410) || (dev->device_id == 0x2420)))
+			tmp |= 1 << 27;
+		else
+			tmp |= 1 << gpio;
+		OUTL(tmp, base);
+
+		/* Set GPIO to OUTPUT */
+		tmp = INL(base + 0x04);
+		tmp &= ~(1 << gpio);
+		OUTL(tmp, base + 0x04);
+
+		/* Raise GPIO line */
+		tmp = INL(base + 0x0C);
+		tmp |= 1 << gpio;
+		OUTL(tmp, base + 0x0C);
+	} else {
+		gpio -= 32;
+
+		/* Set line to GPIO */
+		tmp = INL(base + 0x30);
+		tmp |= 1 << gpio;
+		OUTL(tmp, base + 0x30);
+
+		/* Set GPIO to OUTPUT */
+		tmp = INL(base + 0x34);
+		tmp &= ~(1 << gpio);
+		OUTL(tmp, base + 0x34);
+
+		/* Raise GPIO line */
+		tmp = INL(base + 0x38);
+		tmp |= 1 << gpio;
+		OUTL(tmp, base + 0x38);
+	}
+}
+
+/**
+ * Suited for ASUS P4B266: socket478 + intel 845D + ICH2.
+ */
+static int board_asus_p4b266(const char *name)
+{
 	struct pci_dev *dev;
-	uint16_t gpiobar;
-	uint32_t reg32;
 
-	dev = pci_dev_find(ich_vendor, ich_device);	/* Intel ICHx LPC */
+	dev = pci_dev_find(0x8086, 0x2440);	/* Intel ICH2 ISA Bridge */
 	if (!dev) {
-		fprintf(stderr, "\nERROR: ICHx LPC dev %4x:%4x not found.\n",
-			ich_vendor, ich_device);
+		fprintf(stderr, "\nERROR: Intel ICH2 ISA Bridge not found.\n");
 		return -1;
 	}
 
-	/* Use GPIOBASE register to find the I/O space for GPIO. */
-	gpiobar = pci_read_word(dev, gpiobase_reg) & gp_lvl_bitmask;
+	ich_gpio_raise(dev, 22);
 
-	/* Set specified GPIO to high. */
-	reg32 = INL(gpiobar + gp_lvl);
-	reg32 |= (1 << gpio_bit);
-	OUTL(reg32, gpiobar + gp_lvl);
+	return 0;
+}
 
+/**
+ * Suited for Acorp 6A815EPD: socket 370 + intel 815 + ICH2.
+ */
+static int board_acorp_6a815epd(const char *name)
+{
+	struct pci_dev *dev;
+
+	dev = pci_dev_find(0x8086, 0x2440);	/* Intel ICH2 LPC */
+	if (!dev) {
+		fprintf(stderr, "\nERROR: Intel ICH2 ISA bridge not found.\n");
+		return -1;
+	}
+
+	ich_gpio_raise(dev, 22); /* Lower Blocks Lock -- pin 7 of PLCC32 */
+	ich_gpio_raise(dev, 23); /* Top Block Lock -- pin 8 of PLCC32 */
+
 	return 0;
 }
 
 /**
- * Suited for ASUS P4B266.
+ * Suited for Asus P4P800-E Deluxe: Intel socket478 + 865PE + ICH5R.
  */
-static int ich2_gpio22_raise(const char *name)
+static int board_asus_p4p800(const char *name)
 {
-	return ich_gpio_raise(name, 0x8086, 0x2440, 0x58, 0x0c, 0xffc0, 22);
+	struct pci_dev *dev;
+
+	dev = pci_dev_find(0x8086, 0x24D0);	/* Intel ICH5R ISA Bridge */
+	if (!dev) {
+		fprintf(stderr, "\nERROR: Intel ICH5 ISA Bridge not found.\n");
+		return -1;
+	}
+
+	ich_gpio_raise(dev, 21);
+
+	return 0;
 }
 
 /**
- * Suited for the Dell PowerEdge 1850. All parameters except the last one are
- * documented in the public Intel 82801EB ICH5 / 82801ER ICH5R datasheet. The
- * last parameter (GPIO number) has to be in the range [16,31] according to
- * said Intel datasheet and was found by exhaustive search.
+ * Suited for Dell Poweredge 1850: Intel PPGA604 + E7520 + ICH5R.
  */
-static int ich5_gpio23_raise(const char *name)
+static int board_dell_pe_1850(const char *name)
 {
-	return ich_gpio_raise(name, 0x8086, 0x24d0, 0x58, 0x0c, 0xffc0, 23);
+	struct pci_dev *dev;
+
+	dev = pci_dev_find(0x8086, 0x24D0);	/* Intel ICH5R ISA Bridge */
+	if (!dev) {
+		fprintf(stderr, "\nERROR: Intel ICH5 ISA Bridge not found.\n");
+		return -1;
+	}
+
+	ich_gpio_raise(dev, 23);
+
+	return 0;
 }
 
 /**
- * Suited for MSI MS-7046.
+ * Suited for MSI MS-7046: LGA775 + 915P + ICH6.
  */
-static int ich6_gpio19_raise(const char *name)
+static int board_msi_ms7046(const char *name)
 {
-	return ich_gpio_raise(name, 0x8086, 0x2640, 0x48, 0x0c, 0xffc0, 19);
+	struct pci_dev *dev;
+
+	dev = pci_dev_find(0x8086, 0x2640);	/* Intel ICH6 LPC Interface */
+	if (!dev) {
+		fprintf(stderr, "\nERROR: Intel ICH9R LPC not found.\n");
+		return -1;
+	}
+
+	ich_gpio_raise(dev, 19);
+
+	return 0;
 }
 
+/**
+ * Suited for Kontron 986LCD-M: socket478 + 915GM + ICH7R.
+ */
 static int board_kontron_986lcd_m(const char *name)
 {
 	struct pci_dev *dev;
-	uint16_t gpiobar;
-	uint32_t val;
 
-#define ICH7_GPIO_LVL2 0x38
-
 	dev = pci_dev_find(0x8086, 0x27b8);	/* Intel ICH7 LPC */
 	if (!dev) {
-		// This will never happen on this board
-		fprintf(stderr, "\nERROR: ICH7 LPC bridge not found.\n");
+		fprintf(stderr, "\nERROR: Intel ICH7 LPC bridge not found.\n");
 		return -1;
 	}
 
-	/* Use GPIOBASE register to find where the GPIO is mapped. */
-	gpiobar = pci_read_word(dev, 0x48) & 0xfffc;
+	ich_gpio_raise(dev, 34); /* #TBL */
+	ich_gpio_raise(dev, 35); /* #WP */
 
-	val = INL(gpiobar + ICH7_GPIO_LVL2);	/* GP_LVL2 */
-	printf_debug("\nGPIOBAR=0x%04x GP_LVL: 0x%08x\n", gpiobar, val);
+	return 0;
+}
 
-	/* bit 2 (0x04) = 0 #TBL --> bootblock locking = 1
-	 * bit 2 (0x04) = 1 #TBL --> bootblock locking = 0
-	 * bit 3 (0x08) = 0 #WP --> block locking = 1
-	 * bit 3 (0x08) = 1 #WP --> block locking = 0
-	 *
-	 * To enable full block locking, you would do:
-	 *     val &= ~ ((1 << 2) | (1 << 3));
-	 */
-	val |= (1 << 2) | (1 << 3);
+/**
+ * Suited for Abit IP35: Intel P35 + ICH9R.
+ */
+static int board_abit_ip35(const char *name)
+{
+	struct pci_dev *dev;
 
-	OUTL(val, gpiobar + ICH7_GPIO_LVL2);
+	dev = pci_dev_find(0x8086, 0x2916);	/* Intel ICH9R LPC Interface */
+	if (!dev) {
+		fprintf(stderr, "\nERROR: Intel ICH9R LPC not found.\n");
+		return -1;
+	}
 
+	ich_gpio_raise(dev, 16);
+
 	return 0;
 }
 
@@ -881,32 +978,6 @@
 }
 
 /**
- * Suited for Abit IP35: Intel P35 + ICH9R.
- */
-static int board_abit_ip35(const char *name)
-{
-	struct pci_dev *dev;
-	uint16_t base;
-	uint8_t tmp;
-
-	dev = pci_dev_find(0x8086, 0x2916);	/* Intel ICH9R LPC Interface */
-	if (!dev) {
-		fprintf(stderr, "\nERROR: Intel ICH9R LPC not found.\n");
-		return -1;
-	}
-
-	/* get LPC GPIO base */
-	base = pci_read_long(dev, 0x48) & 0x0000FFC0;
-
-	/* Raise GPIO 16 */
-	tmp = INB(base + 0x0E);
-	tmp |= 0x01;
-	OUTB(tmp, base + 0x0E);
-
-	return 0;
-}
-
-/**
  * Suited for Asus A7V8X: VIA KT400 + VT8235 + IT8703F-A
  */
 static int board_asus_a7v8x(const char *name)
@@ -1009,32 +1080,6 @@
 }
 
 /**
- * Suited for Asus P4P800-E Deluxe: Intel Intel 865PE + ICH5R.
- */
-static int board_asus_p4p800(const char *name)
-{
-	struct pci_dev *dev;
-	uint16_t base;
-	uint8_t tmp;
-
-	dev = pci_dev_find(0x8086, 0x24D0);	/* Intel ICH5R ISA Bridge */
-	if (!dev) {
-		fprintf(stderr, "\nERROR: Intel ICH5R ISA Bridge not found.\n");
-		return -1;
-	}
-
-	/* get PM IO base */
-	base = pci_read_long(dev, 0x58) & 0x0000FFC0;
-
-	/* Raise GPIO 21 */
-	tmp = INB(base + 0x0E);
-	tmp |= 0x20;
-	OUTB(tmp, base + 0x0E);
-
-	return 0;
-}
-
-/**
  * Below is the list of boards which need a special "board enable" code in
  * flashrom before their ROM chip can be accessed/written to.
  *
@@ -1073,12 +1118,12 @@
 	{0x1106, 0x3189, 0x1043, 0x807F,  0x1106, 0x3065, 0x1043, 0x80ED, NULL,         NULL,          "ASUS",        "A7V600-X",           board_asus_a7v600x},
 	{0x1106, 0x3189, 0x1043, 0x807F,  0x1106, 0x3177, 0x1043, 0x808C, NULL,         NULL,          "ASUS",        "A7V8X",              board_asus_a7v8x},
 	{0x1106, 0x3177, 0x1043, 0x80A1,  0x1106, 0x3205, 0x1043, 0x8118, NULL,         NULL,          "ASUS",        "A7V8X-MX SE",        board_asus_a7v8x_mx},
-	{0x8086, 0x1a30, 0x1043, 0x8070,  0x8086, 0x244b, 0x1043, 0x8028, NULL,         NULL,          "ASUS",        "P4B266",             ich2_gpio22_raise},
+	{0x8086, 0x1a30, 0x1043, 0x8070,  0x8086, 0x244b, 0x1043, 0x8028, NULL,         NULL,          "ASUS",        "P4B266",             board_asus_p4b266},
 	{0x8086, 0x2570, 0x1043, 0x80F2,  0x105A, 0x3373, 0x1043, 0x80F5, NULL,         NULL,          "ASUS",        "P4P800-E Deluxe",    board_asus_p4p800},
 	{0x10B9, 0x1541,      0,      0,  0x10B9, 0x1533,      0,      0, "asus",       "p5a",         "ASUS",        "P5A",                board_asus_p5a},
 	{0x10DE, 0x0030, 0x1043, 0x818a,  0x8086, 0x100E, 0x1043, 0x80EE, NULL,         NULL,          "ASUS",        "P5ND2-SLI Deluxe",   board_asus_p5nd2_sli},
 	{0x1106, 0x3149, 0x1565, 0x3206,  0x1106, 0x3344, 0x1565, 0x1202, NULL,         NULL,          "Biostar",     "P4M80-M4",           it8705_rom_write_enable},
-	{0x8086, 0x3590, 0x1028, 0x016c,  0x1000, 0x0030, 0x1028, 0x016c, NULL,         NULL,          "Dell",        "PowerEdge 1850",     ich5_gpio23_raise},
+	{0x8086, 0x3590, 0x1028, 0x016c,  0x1000, 0x0030, 0x1028, 0x016c, NULL,         NULL,          "Dell",        "PowerEdge 1850",     board_dell_pe_1850},
 	{0x1106, 0x3038, 0x1019, 0x0996,  0x1106, 0x3177, 0x1019, 0x0996, NULL,         NULL,          "Elitegroup",  "K7VTA3",             it8705f_write_enable_2e},
 	{0x1106, 0x3177, 0x1106, 0x3177,  0x1106, 0x3059, 0x1695, 0x3005, NULL,         NULL,          "EPoX",        "EP-8K5A2",           board_epox_ep_8k5a2},
 	{0x10EC, 0x8139, 0x1695, 0x9001,  0x11C1, 0x5811, 0x1695, 0x9015, NULL,         NULL,          "EPoX",        "EP-8RDA3+",          board_epox_ep_8rda3plus},
@@ -1103,7 +1148,7 @@
 	{0x13f6, 0x0111, 0x1462, 0x5900,  0x1106, 0x3177, 0x1106,      0, "msi",        "kt4ultra",    "MSI",         "MS-6590 (KT4 Ultra)",board_msi_kt4v},
 	{0x1106, 0x3149, 0x1462, 0x7094,  0x10ec, 0x8167, 0x1462, 0x094c, NULL,         NULL,          "MSI",         "MS-6702E (K8T Neo2-F)",w83627thf_gpio4_4_raise_2e},
 	{0x1106, 0x0571, 0x1462, 0x7120,       0,      0,      0,      0, "msi",        "kt4v",        "MSI",         "MS-6712 (KT4V)",     board_msi_kt4v},
-	{0x8086, 0x2658, 0x1462, 0x7046,  0x1106, 0x3044, 0x1462, 0x046d, NULL,         NULL,          "MSI",         "MS-7046",            ich6_gpio19_raise},
+	{0x8086, 0x2658, 0x1462, 0x7046,  0x1106, 0x3044, 0x1462, 0x046d, NULL,         NULL,          "MSI",         "MS-7046",            board_msi_ms7046},
 	{0x10de, 0x005e,      0,      0,       0,      0,      0,      0, "msi",        "k8n-neo3",    "MSI",         "MS-7135 (K8N Neo3)", w83627thf_gpio4_4_raise_4e},
 	{0x1106, 0x3104, 0x1297, 0xa238,  0x1106, 0x3059, 0x1297, 0xc063, NULL,         NULL,          "Shuttle",     "AK38N",              it8705f_write_enable_2e},
 	{0x10DE, 0x0050, 0x1297, 0x5036,  0x1412, 0x1724, 0x1297, 0x5036, NULL,         NULL,          "Shuttle",     "FN25",               board_shuttle_fn25},


More information about the flashrom mailing list