[flashrom] [PATCH] Check availability of GPO lines on Intel PIIX4

Mattias Mattsson vitplister at gmail.com
Sun Jul 18 06:15:25 CEST 2010


Hi,

I'm not a skilled programmer so this patch may look rather
ugly. (Suggestions to improve it are very welcome.)

Anyways, this changes the intel_piix4_gpo_set() function to always
check the GENCFG and XBCS register for the availability of the
requested GPO line (unless called with safe=0) before raising/lowering
it. This behaviour was suggested by Michael Karcher on the flashrom
mailing list and this is an attempt implementing it.

Also adds a board enable for Asus P2B-N. Probe/Read/Write/Erease
tested and works with this board.

Signed-off-by: Mattias Mattsson <vitplister at gmail.com>


Index: board_enable.c
===================================================================
--- board_enable.c	(revision 1091)
+++ board_enable.c	(working copy)
@@ -947,13 +947,67 @@
 }
 
 /**
+ * Helper function to check if a given gpo line is available on Intel PIIX4{,E,M}.
+ */
+static int intel_piix4_gpo_available(unsigned int gpo, struct pci_dev *pci_dev)
+{
+
+	uint32_t gencfg;
+	uint16_t xbcs;
+
+	gencfg = pci_read_long(pci_dev, 0xB0); /* GENCFG */
+	xbcs   = pci_read_word(pci_dev, 0x4E); /* XBCS */
+
+	if ((gpo == 0)) {
+		return 1;					/* GPO0 is always available */
+
+	} else if ((gpo >=  1) && (gpo <=  7)) {
+		return ((gencfg & 1) == 0);			/* GENCFG bit 0 */
+
+	} else if ((gpo == 8)) {
+		return -1;					/* GPO8 is never available */
+
+	} else if ((gpo >=  9) && (gpo <= 11)) {
+		return ((gencfg & (1 << (gpo - 1))) == 0);	/* GENCFG bit 8-10 */
+
+	} else if ((gpo >=  12) && (gpo <= 14)) {
+		return ((xbcs & (1 << 8)) == 0);		/* XBCS bit 8 */
+
+	} else if ((gpo >= 15) && (gpo <= 16)) {
+		return ((gencfg & (1 << 17)) == 1);		/* GENCFG bit 17 */
+
+	} else if ((gpo >= 17) && (gpo <= 21)) {
+		return ((gencfg & (1 << (gpo + 1))) == 1);	/* GENCFG bit 18-22 */
+
+	} else if ((gpo >= 22) && (gpo <= 23)) {
+		return ((gencfg & (1 << 28)) == 1);		/* GENCFG bit 28 */
+
+	} else if ((gpo >= 24) && (gpo <=  26)) {
+		return ((gencfg & (1 << (gpo + 5))) == 1);	/* GENCFG bit 29-31 */
+
+	} else if ((gpo >= 27) && (gpo <= 28)) {
+		return 1;					/* GPO27-28 is always available */
+
+	} else if ((gpo == 29)) {
+		return ((xbcs & (1 << 8)) == 0);		/* XBCS bit 8 */
+
+	} else if ((gpo == 30)) {
+		return 1;					/* GPO30 is always available */
+
+	} else {
+		return -1;
+	}
+}
+
+/**
  * Helper function to raise/drop a given gpo line on Intel PIIX4{,E,M}.
  */
-static int intel_piix4_gpo_set(unsigned int gpo, int raise)
+static int intel_piix4_gpo_set(unsigned int gpo, int raise, int safe)
 {
 	unsigned int gpo_byte, gpo_bit;
 	struct pci_dev *dev;
 	uint32_t tmp, base;
+	uint16_t tmp2;
 
 	dev = pci_dev_find(0x8086, 0x7110);	/* Intel PIIX4 ISA bridge */
 	if (!dev) {
@@ -967,36 +1021,86 @@
 		return -1;
 	}
 
-	/* these are dual function pins which are most likely in use already */
-	if (((gpo >= 1) && (gpo <= 7)) ||
-	    ((gpo >= 9) && (gpo <= 21)) || (gpo == 29)) {
-		msg_perr("\nERROR: Unsupported PIIX4 GPO%d.\n", gpo);
-		return -1;
-	}
+	if (safe) {
+		if (intel_piix4_gpo_available(gpo, dev) == -1) {
+			msg_perr("\nERROR: Intel PIIX4 GPO%d not available.\n", gpo);
+			return -1;
+		}
+	} else {
+		/* dual function that need special enable. */
 
-	/* dual function that need special enable. */
-	if ((gpo >= 22) && (gpo <= 26)) {
-		tmp = pci_read_long(dev, 0xB0); /* GENCFG */
+		tmp  = pci_read_long(dev, 0xB0); /* GENCFG */
+		tmp2 = pci_read_word(dev, 0x4E); /* XBCS */
 		switch (gpo) {
-		case 22: /* XBUS: XDIR#/GPO22 */
-		case 23: /* XBUS: XOE#/GPO23 */
-			tmp |= 1 << 28;
+		case 0:
 			break;
-		case 24: /* RTCSS#/GPO24 */
-			tmp |= 1 << 29;
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			tmp &= ~(1 << 0);  /* GENCFG bit  0: 0 = GPI0+GPO1-7 / 1 = IOCHK#+LA17-23 */
 			break;
-		case 25: /* RTCALE/GPO25 */
-			tmp |= 1 << 30;
+		case 8:
 			break;
-		case 26: /* KBCSS#/GPO26 */
-			tmp |= 1 << 31;
+		case 9:
+			tmp &= ~(1 << 8);  /* GENCFG bit  8: 0 = GPI2+GPO9 / 1 = PC/PCI REQA+GNTA */
 			break;
-		}
-		pci_write_long(dev, 0xB0, tmp);
-	}
+		case 10:
+			tmp &= ~(1 << 9);  /* GENCFG bit  9: 0 = GPI3+GPO10 / 1 = PC/PCI REQB+GNTB */
+			break;
+		case 11:
+			tmp &= ~(1 << 10); /* GENCFG bit 10: 0 = GPI4+GPO11 / 1 = PC/PCI REQC+GNTC */
+			break;
+		case 12:
+		case 13:
+		case 14:
+		case 29:
+			tmp2 &= ~(1 << 8); /* XBCS bit 8: 0 = GPI5+GPO12-14+GPO29 / 1 = APIC Chip select */
+			break;
+		case 15:
+		case 16:
+			tmp |= 1 << 17;    /* GENCFG bit 17: 0 = SUSB#+SUSC# / 1 = GPO15+GPO16 */
+			break;
+		case 17:
+			tmp |= 1 << 18;    /* GENCFG bit 18: 0 = CPU_STP# / 1 = GPO17 */
+			break;
+		case 18:
+			tmp |= 1 << 19;    /* GENCFG bit 19: 0 = PCI_STP# / 1 = GPO18 */
+			break;
+		case 19:
+			tmp |= 1 << 20;    /* GENCFG bit 20: 0 = ZZ / 1 = GPO19 */
+			break;
+		case 20:
+			tmp |= 1 << 21;    /* GENCFG bit 21: 0 = SUS_STAT1# / 1 = GPO20 */
+			break;
+		case 21:
+			tmp |= 1 << 22;    /* GENCFG bit 22: 0 = SUS_STAT2# / 1 = GPO21 */
+			break;
+		case 22:
+		case 23:
+			tmp |= 1 << 28;    /* GENCFG bit 28: 0 = XDIR#+XDIR# / 1 = GPO22+GPO23 */
+			break;
+		case 24:
+			tmp |= 1 << 29;    /* GENCFG bit 29: 0 = RTCSS# / 1 = GPO24 */
+			break;
+		case 25:
+			tmp |= 1 << 30;    /* GENCFG bit 30: 0 = RTCALE / 1 = GPO25 */
+			break;
+		case 26:
+			tmp |= 1 << 31;    /* GENCFG bit 31: 0 = KBCSS# / 1 = GPO26 */
+			break;
+		case 27:
+		case 28:
+		case 30:
+			break;
+                }
+                pci_write_long(dev, 0xB0, tmp);
+                pci_write_word(dev, 0x4E, tmp2);
+        }
 
-	/* GPO {0,8,27,28,30} are always available. */
-
 	dev = pci_dev_find(0x8086, 0x7113);	/* Intel PIIX4 PM */
 	if (!dev) {
 		msg_perr("\nERROR: Intel PIIX4 PM not found.\n");
@@ -1023,15 +1127,23 @@
  */
 static int board_epox_ep_bx3(void)
 {
-	return intel_piix4_gpo_set(22, 1);
+	return intel_piix4_gpo_set(22, 1, 1);
 }
 
 /**
+ * Suited for Asus P2B-N
+ */
+static int intel_piix4_gpo18_lower(void)
+{
+        return intel_piix4_gpo_set(18, 0, 1);
+}
+
+/**
  * Suited for Intel SE440BX-2
  */
 static int intel_piix4_gpo27_lower(void)
 {
-        return intel_piix4_gpo_set(27, 0);
+        return intel_piix4_gpo_set(27, 0, 1);
 }
 
 /**
@@ -1672,6 +1784,7 @@
 	{0x10de, 0x0264, 0x1043, 0x81bc,  0x10de, 0x02f0, 0x1043, 0x81cd, NULL,          NULL,         NULL,          "ASUS",        "A8N-VM CSM",            0,   NT, w83627ehf_gpio24_raise_2e},
 	{0x10DE, 0x0264, 0x1043, 0x81C0,  0x10DE, 0x0260, 0x1043, 0x81C0, NULL,          NULL,         NULL,          "ASUS",        "M2NBP-VM CSM",          0,   OK, nvidia_mcp_gpio0_raise},
 	{0x1106, 0x1336, 0x1043, 0x80ed,  0x1106, 0x3288, 0x1043, 0x8249, NULL,          NULL,         NULL,          "ASUS",        "M2V-MX",                0,   OK, via_vt823x_gpio5_raise},
+	{0x8086, 0x7190,      0,      0,  0x8086, 0x7191,      0,      0, "^P2B-N$",     NULL,         NULL,          "ASUS",        "P2B-N",                 0,   OK, intel_piix4_gpo18_lower},
 	{0x8086, 0x1A30, 0x1043, 0x8025,  0x8086, 0x244B, 0x104D, 0x80F0, NULL,          NULL,         NULL,          "ASUS",        "P4B266-LM",             0,   OK, intel_ich_gpio21_raise},
 	{0x8086, 0x1a30, 0x1043, 0x8070,  0x8086, 0x244b, 0x1043, 0x8028, NULL,          NULL,         NULL,          "ASUS",        "P4B266",                0,   OK, intel_ich_gpio22_raise},
 	{0x8086, 0x1A30, 0x1043, 0x8088,  0x8086, 0x24C3, 0x1043, 0x8089, NULL,          NULL,         NULL,          "ASUS",        "P4B533-E",              0,   NT, intel_ich_gpio22_raise},




More information about the flashrom mailing list