The new intel_ich_gpio_raise function should be general for all intel ich southbridges. There are a few comments to this function, which should be considered before using this function. Plus, this function does not only raise the gpio line, it switches the signal to gpio and sets it to output as well.
A few boards have been moved around to sit below the intel_ich_gpio_raise function which makes this patch more unsightly than it could be.
Signed-off-by: Luc Verhaegen libv@skynet.be --- board_enable.c | 326 ++++++++++++++++++++++++++++++++------------------------ 1 files changed, 189 insertions(+), 137 deletions(-)
diff --git a/board_enable.c b/board_enable.c index 21b91f1..2332209 100644 --- a/board_enable.c +++ b/board_enable.c @@ -523,32 +523,6 @@ static int board_epox_ep_bx3(const char *name) }
/** - * 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,103 +564,233 @@ static int board_artecgroup_dbe6x(const char *name) }
/** - * 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. + * + * In hardware, the GPIO BARs have the lower bits (5:1) zeroed, starting + * with a mobile ich9 version bits 6:1 are zeroed. The 0xFFC0 mask should + * catch all just fine. + */ +static void intel_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 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 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; + intel_ich_gpio_raise(dev, 22); + + return 0; +}
- /* Set specified GPIO to high. */ - reg32 = INL(gpiobar + gp_lvl); - reg32 |= (1 << gpio_bit); - OUTL(reg32, gpiobar + gp_lvl); +/** + * 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; + } + + intel_ich_gpio_raise(dev, 22); /* Lower Blocks Lock -- pin 7 of PLCC32 */ + intel_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; + } + + intel_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. + * + * The GPIO number has to be in the range [16,31] according to the public Intel + * 82801EB ICH5 / 82801ER ICH5R datasheet and was found by exhaustive search. */ -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; + } + + intel_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; + } + + intel_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; + intel_ich_gpio_raise(dev, 34); /* #TBL */ + intel_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; + + dev = pci_dev_find(0x8086, 0x2916); /* Intel ICH9R LPC Interface */ + if (!dev) { + fprintf(stderr, "\nERROR: Intel ICH9R LPC not found.\n"); + return -1; + }
- OUTL(val, gpiobar + ICH7_GPIO_LVL2); + intel_ich_gpio_raise(dev, 16);
return 0; } @@ -881,32 +985,6 @@ static int board_mitac_6513wu(const char *name) }
/** - * 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 +1087,6 @@ static int board_asus_a7v600x(const char *name) }
/** - * 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 +1125,12 @@ struct board_pciid_enable board_pciid_enables[] = { {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 +1155,7 @@ struct board_pciid_enable board_pciid_enables[] = { {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},