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@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},