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(a)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},