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 <[email protected]>


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

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to