Very untested and new. Sent in to show off what is being worked on and to get first impressions.
Last i tried it worked fine on: * Winbond W83627EHF on MSI Fuzzy CN700 (nothing needed, just detection). * Winbond W83697HF on Asus 7V8X-MX SE (needing superio rom write enable) To be tested still: * it8705F rom write enable (have shuttle board here that i should still test on). * it87 spi code (have nonspi board here that i should still test on). Luc Verhaegen.
>From f98cbb703f2bbbb918a87eebcd10c4cc1bd457f9 Mon Sep 17 00:00:00 2001 From: Luc Verhaegen <l...@skynet.be> Date: Tue, 12 Jan 2010 13:57:21 +0100 Subject: [PATCH] WIP. --- Makefile | 2 +- board_enable.c | 411 +++++++------------------------------------------ chipset_enable.c | 1 + flash.h | 37 +---- flashrom.c | 19 --- internal.c | 20 +-- it87spi.c | 202 ++++-------------------- spi.c | 1 + superio.c | 454 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ superio.h | 107 +++++++++++++ wbsio_spi.c | 48 ++----- 11 files changed, 676 insertions(+), 626 deletions(-) create mode 100644 superio.c create mode 100644 superio.h diff --git a/Makefile b/Makefile index 423e315..dfa6b66 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ CONFIG_PRINT_WIKI ?= no ifeq ($(CONFIG_INTERNAL), yes) FEATURE_CFLAGS += -D'INTERNAL_SUPPORT=1' -PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o it87spi.o ichspi.o sb600spi.o wbsio_spi.o +PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o it87spi.o ichspi.o sb600spi.o wbsio_spi.o superio.o NEED_PCI := yes endif diff --git a/board_enable.c b/board_enable.c index abe1d47..e5a620d 100644 --- a/board_enable.c +++ b/board_enable.c @@ -27,73 +27,7 @@ #include <string.h> #include <fcntl.h> #include "flash.h" - -/* - * Helper functions for many Winbond Super I/Os of the W836xx range. - */ -/* Enter extended functions */ -void w836xx_ext_enter(uint16_t port) -{ - OUTB(0x87, port); - OUTB(0x87, port); -} - -/* Leave extended functions */ -void w836xx_ext_leave(uint16_t port) -{ - OUTB(0xAA, port); -} - -/* Generic Super I/O helper functions */ -uint8_t sio_read(uint16_t port, uint8_t reg) -{ - OUTB(reg, port); - return INB(port + 1); -} - -void sio_write(uint16_t port, uint8_t reg, uint8_t data) -{ - OUTB(reg, port); - OUTB(data, port + 1); -} - -void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask) -{ - uint8_t tmp; - - OUTB(reg, port); - tmp = INB(port + 1) & ~mask; - OUTB(tmp | (data & mask), port + 1); -} - -/* Not used yet. */ -#if 0 -static int enable_flash_decode_superio(void) -{ - int ret; - uint8_t tmp; - - switch (superio.vendor) { - case SUPERIO_VENDOR_NONE: - ret = -1; - break; - case SUPERIO_VENDOR_ITE: - enter_conf_mode_ite(superio.port); - /* Enable flash mapping. Works for most old ITE style SuperI/O. */ - tmp = sio_read(superio.port, 0x24); - tmp |= 0xfc; - sio_write(superio.port, 0x24, tmp); - exit_conf_mode_ite(superio.port); - ret = 0; - break; - default: - printf_debug("Unhandled SuperI/O type!\n"); - ret = -1; - break; - } - return ret; -} -#endif +#include "superio.h" /** * Winbond W83627HF: Raise GPIO24. @@ -102,37 +36,9 @@ static int enable_flash_decode_superio(void) * - Agami Aruma * - IWILL DK8-HTX */ -static int w83627hf_gpio24_raise(uint16_t port, const char *name) -{ - w836xx_ext_enter(port); - - /* Is this the W83627HF? */ - if (sio_read(port, 0x20) != 0x52) { /* Super I/O device ID reg. */ - fprintf(stderr, "\nERROR: %s: W83627HF: Wrong ID: 0x%02X.\n", - name, sio_read(port, 0x20)); - w836xx_ext_leave(port); - return -1; - } - - /* PIN89S: WDTO/GP24 multiplex -> GPIO24 */ - sio_mask(port, 0x2B, 0x10, 0x10); - - /* Select logical device 8: GPIO port 2 */ - sio_write(port, 0x07, 0x08); - - sio_mask(port, 0x30, 0x01, 0x01); /* Activate logical device. */ - sio_mask(port, 0xF0, 0x00, 0x10); /* GPIO24 -> output */ - sio_mask(port, 0xF2, 0x00, 0x10); /* Clear GPIO24 inversion */ - sio_mask(port, 0xF1, 0x10, 0x10); /* Raise GPIO24 */ - - w836xx_ext_leave(port); - - return 0; -} - -static int w83627hf_gpio24_raise_2e(const char *name) +static int w83627hf_gpio24_raise(const char *name) { - return w83627hf_gpio24_raise(0x2e, name); + return superio_gpio_set(24, 1); } /** @@ -142,95 +48,9 @@ static int w83627hf_gpio24_raise_2e(const char *name) * - MSI K8T Neo2-F * - MSI K8N-NEO3 */ -static int w83627thf_gpio4_4_raise(uint16_t port, const char *name) -{ - w836xx_ext_enter(port); - - /* Is this the W83627THF? */ - if (sio_read(port, 0x20) != 0x82) { /* Super I/O device ID reg. */ - fprintf(stderr, "\nERROR: %s: W83627THF: Wrong ID: 0x%02X.\n", - name, sio_read(port, 0x20)); - w836xx_ext_leave(port); - return -1; - } - - /* PINxxxxS: GPIO4/bit 4 multiplex -> GPIOXXX */ - - sio_write(port, 0x07, 0x09); /* Select LDN 9: GPIO port 4 */ - sio_mask(port, 0x30, 0x02, 0x02); /* Activate logical device. */ - sio_mask(port, 0xF4, 0x00, 0x10); /* GPIO4 bit 4 -> output */ - sio_mask(port, 0xF6, 0x00, 0x10); /* Clear GPIO4 bit 4 inversion */ - sio_mask(port, 0xF5, 0x10, 0x10); /* Raise GPIO4 bit 4 */ - - w836xx_ext_leave(port); - - return 0; -} - -static int w83627thf_gpio4_4_raise_2e(const char *name) -{ - return w83627thf_gpio4_4_raise(0x2e, name); -} - -static int w83627thf_gpio4_4_raise_4e(const char *name) -{ - return w83627thf_gpio4_4_raise(0x4e, name); -} - -/** - * w83627: Enable MEMW# and set ROM size to max. - */ -static void w836xx_memw_enable(uint16_t port) -{ - w836xx_ext_enter(port); - if (!(sio_read(port, 0x24) & 0x02)) { /* Flash ROM enabled? */ - /* Enable MEMW# and set ROM size select to max. (4M). */ - sio_mask(port, 0x24, 0x28, 0x28); - } - w836xx_ext_leave(port); -} - -/** - * Suited for: - * - EPoX EP-8K5A2: VIA KT333 + VT8235. - * - Albatron PM266A Pro: VIA P4M266A + VT8235. - * - Shuttle AK31 (all versions): VIA KT266 + VT8233. - * - ASUS A7V8X-MX SE and A7V400-MX: AMD K7 + VIA KM400A + VT8235 - * - Tyan S2498 (Tomcat K7M): AMD Geode NX + VIA KM400 + VT8237. - */ -static int w836xx_memw_enable_2e(const char *name) +static int w83627thf_gpio44_raise(const char *name) { - w836xx_memw_enable(0x2E); - - return 0; -} - -/** - * - */ -static int it8705f_write_enable(uint8_t port, const char *name) -{ - enter_conf_mode_ite(port); - sio_mask(port, 0x24, 0x04, 0x04); /* Flash ROM I/F Writes Enable */ - exit_conf_mode_ite(port); - - return 0; -} - -/** - * Suited for: - * - AOpen vKM400Am-S: VIA KM400 + VT8237 + IT8705F. - * - Biostar P4M80-M4: VIA P4M800 + VT8237 + IT8705AF - * - Elitegroup K7S6A: SiS745 + ITE IT8705F - * - Elitegroup K7VTA3: VIA Apollo KT266/A/333 + VIA VT8235 + ITE IT8705F - * - GIGABYTE GA-7VT600: VIA KT600 + VT8237 + IT8705 - * - Shuttle AK38N: VIA KT333CF + VIA VT8235 + ITE IT8705F - * - * SIS950 superio probably requires the same flash write enable. - */ -static int it8705f_write_enable_2e(const char *name) -{ - return it8705f_write_enable(0x2e, name); + return superio_gpio_set(44, 1); } /** @@ -307,31 +127,24 @@ static int via_vt823x_gpio9_raise(const char *name) } /** - * Suited for VIAs EPIA M and MII, and maybe other CLE266 based EPIAs. - * - * We don't need to do this for EPIA M when using coreboot, GPIO15 is never - * lowered there. + * Suited for: + * - MSI KT4V and KT4V-L: AMD K7 + VIA KT400 + VT8235 + W83697HF. + * - MSI KT4 Ultra: AMD K7 + VIA KT400 + VT8235 + W83697HF. */ -static int via_vt823x_gpio15_raise(const char *name) +static int via_vt823x_gpio12_raise(const char *name) { - return via_vt823x_gpio_set(15, 1); + return via_vt823x_gpio_set(12, 1); } /** - * Winbond W83697HF Super I/O + VIA VT8235 southbridge + * Suited for VIAs EPIA M and MII, and maybe other CLE266 based EPIAs. * - * Suited for: - * - MSI KT4V and KT4V-L: AMD K7 + VIA KT400 + VT8235 - * - MSI KT4 Ultra: AMD K7 + VIA KT400 + VT8235 + * We don't need to do this for EPIA M when using coreboot, GPIO15 is never + * lowered there. */ -static int board_msi_kt4v(const char *name) +static int via_vt823x_gpio15_raise(const char *name) { - int ret; - - ret = via_vt823x_gpio_set(12, 1); - w836xx_memw_enable(0x2E); - - return ret; + return via_vt823x_gpio_set(15, 1); } /** @@ -973,8 +786,6 @@ static int board_msi_651ml(const char *name) temp |= (1 << 0); /* Raise output? */ OUTW(temp, base + 0x64); - w836xx_memw_enable(0x2E); - return 0; } @@ -1018,16 +829,9 @@ out: */ static int board_mitac_6513wu(const char *name) { - struct pci_dev *dev; uint16_t rt_port; uint8_t val; - dev = pci_dev_find(0x8086, 0x2410); /* Intel 82801AA ISA bridge */ - if (!dev) { - fprintf(stderr, "\nERROR: Intel 82801AA ISA bridge not found.\n"); - return -1; - } - rt_port = smsc_find_runtime(0x4e, 0x54 /* LPC47U33x */, 0xa); if (rt_port == 0) return -1; @@ -1050,93 +854,7 @@ static int board_mitac_6513wu(const char *name) */ static int board_asus_a7v8x(const char *name) { - uint16_t id, base; - uint8_t tmp; - - /* find the IT8703F */ - w836xx_ext_enter(0x2E); - id = (sio_read(0x2E, 0x20) << 8) | sio_read(0x2E, 0x21); - w836xx_ext_leave(0x2E); - - if (id != 0x8701) { - fprintf(stderr, "\nERROR: IT8703F SuperIO not found.\n"); - return -1; - } - - /* Get the GP567 IO base */ - w836xx_ext_enter(0x2E); - sio_write(0x2E, 0x07, 0x0C); - base = (sio_read(0x2E, 0x60) << 8) | sio_read(0x2E, 0x61); - w836xx_ext_leave(0x2E); - - if (!base) { - fprintf(stderr, "\nERROR: Failed to read IT8703F SuperIO GPIO" - " Base.\n"); - return -1; - } - - /* Raise GP51. */ - tmp = INB(base); - tmp |= 0x02; - OUTB(tmp, base); - - return 0; -} - -/* - * General routine for raising/dropping GPIO lines on the ITE IT8712F. - * There is only some limited checking on the port numbers. - */ -static int -it8712f_gpio_set(unsigned int line, int raise) -{ - unsigned int port; - uint16_t id, base; - uint8_t tmp; - - port = line / 10; - port--; - line %= 10; - - /* Check line */ - if ((port > 4) || /* also catches unsigned -1 */ - ((port < 4) && (line > 7)) || ((port == 4) && (line > 5))) { - fprintf(stderr, - "\nERROR: Unsupported IT8712F GPIO Line %02d.\n", line); - return -1; - } - - /* find the IT8712F */ - enter_conf_mode_ite(0x2E); - id = (sio_read(0x2E, 0x20) << 8) | sio_read(0x2E, 0x21); - exit_conf_mode_ite(0x2E); - - if (id != 0x8712) { - fprintf(stderr, "\nERROR: IT8712F SuperIO not found.\n"); - return -1; - } - - /* Get the GPIO base */ - enter_conf_mode_ite(0x2E); - sio_write(0x2E, 0x07, 0x07); - base = (sio_read(0x2E, 0x62) << 8) | sio_read(0x2E, 0x63); - exit_conf_mode_ite(0x2E); - - if (!base) { - fprintf(stderr, "\nERROR: Failed to read IT8712F SuperIO GPIO" - " Base.\n"); - return -1; - } - - /* set GPIO. */ - tmp = INB(base + port); - if (raise) - tmp |= 1 << line; - else - tmp &= ~(1 << line); - OUTB(tmp, base + port); - - return 0; + return superio_gpio_set(51, 1); } /** @@ -1144,7 +862,7 @@ it8712f_gpio_set(unsigned int line, int raise) */ static int board_asus_a7v600x(const char *name) { - return it8712f_gpio_set(32, 1); + return superio_gpio_set(32, 1); } /** @@ -1175,62 +893,45 @@ static int board_asus_a7v600x(const char *name) /* Please keep this list alphabetically ordered by vendor/board name. */ struct board_pciid_enable board_pciid_enables[] = { - /* first pci-id set [4], second pci-id set [4], coreboot id [2], vendor name board name max_rom_... flash enable */ - {0x8086, 0x2926, 0x147b, 0x1084, 0x11ab, 0x4364, 0x147b, 0x1084, NULL, NULL, "Abit", "IP35", 0, intel_ich_gpio16_raise}, - {0x105a, 0x0d30, 0x105a, 0x4d33, 0x8086, 0x1130, 0x8086, 0, NULL, NULL, "Acorp", "6A815EPD", 0, board_acorp_6a815epd}, - {0x8086, 0x24D4, 0x1849, 0x24D0, 0x8086, 0x24D5, 0x1849, 0x9739, NULL, NULL, "ASRock", "P4i65GV", 0, intel_ich_gpio23_raise}, - {0x1022, 0x746B, 0, 0, 0, 0, 0, 0, "AGAMI", "ARUMA", "agami", "Aruma", 0, w83627hf_gpio24_raise_2e}, - {0x1106, 0x3177, 0x17F2, 0x3177, 0x1106, 0x3148, 0x17F2, 0x3148, NULL, NULL, "Albatron", "PM266A", 0, w836xx_memw_enable_2e}, - {0x1106, 0x3205, 0x1106, 0x3205, 0x10EC, 0x8139, 0xA0A0, 0x0477, NULL, NULL, "AOpen", "vKM400Am-S", 0, it8705f_write_enable_2e}, - {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, "artecgroup", "dbe61", "Artec Group", "DBE61", 0, board_artecgroup_dbe6x}, - {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, "artecgroup", "dbe62", "Artec Group", "DBE62", 0, board_artecgroup_dbe6x}, - {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3065, 0x1043, 0x80ED, NULL, NULL, "ASUS", "A7V600-X", 0, board_asus_a7v600x}, - {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x808C, NULL, NULL, "ASUS", "A7V8X", 0, board_asus_a7v8x}, - {0x1106, 0x3177, 0x1043, 0x80A1, 0x1106, 0x3205, 0x1043, 0x8118, NULL, NULL, "ASUS", "A7V8X-MX SE", 0, w836xx_memw_enable_2e}, - {0x1106, 0x1336, 0x1043, 0x80ed, 0x1106, 0x3288, 0x1043, 0x8249, NULL, NULL, "ASUS", "M2V-MX", 0, via_vt823x_gpio5_raise}, - {0x8086, 0x1a30, 0x1043, 0x8070, 0x8086, 0x244b, 0x1043, 0x8028, NULL, NULL, "ASUS", "P4B266", 0, intel_ich_gpio22_raise}, - {0x8086, 0x1A30, 0x1043, 0x8025, 0x8086, 0x244B, 0x104D, 0x80F0, NULL, NULL, "ASUS", "P4B266-LM", 0, intel_ich_gpio21_raise}, - {0x8086, 0x2570, 0x1043, 0x80F2, 0x105A, 0x3373, 0x1043, 0x80F5, NULL, NULL, "ASUS", "P4P800-E Deluxe", 0, intel_ich_gpio21_raise}, - {0x10B9, 0x1541, 0, 0, 0x10B9, 0x1533, 0, 0, "asus", "p5a", "ASUS", "P5A", 0, board_asus_p5a}, - {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, "ASUS", "P5ND2-SLI Deluxe", 0, nvidia_mcp_gpio10_raise}, - {0x1106, 0x3149, 0x1565, 0x3206, 0x1106, 0x3344, 0x1565, 0x1202, NULL, NULL, "Biostar", "P4M80-M4", 0, it8705f_write_enable_2e}, - {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, "Dell", "PowerEdge 1850", 0, intel_ich_gpio23_raise}, - {0x1039, 0x5513, 0x1019, 0x0A41, 0x1039, 0x0018, 0, 0, NULL, NULL, "Elitegroup", "K7S6A", 0, it8705f_write_enable_2e}, - {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, "Elitegroup", "K7VTA3", 256, it8705f_write_enable_2e}, - {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3059, 0x1695, 0x3005, NULL, NULL, "EPoX", "EP-8K5A2", 0, w836xx_memw_enable_2e}, - {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, NULL, NULL, "EPoX", "EP-8RDA3+", 0, nvidia_mcp_gpio31_raise}, - {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, "epox", "ep-bx3", "EPoX", "EP-BX3", 0, board_epox_ep_bx3}, - {0x1039, 0x0761, 0, 0, 0x10EC, 0x8168, 0, 0, "gigabyte", "2761gxdk", "GIGABYTE", "GA-2761GXDK", 0, it87xx_probe_spi_flash}, - {0x1106, 0x3227, 0x1458, 0x5001, 0x10ec, 0x8139, 0x1458, 0xe000, NULL, NULL, "GIGABYTE", "GA-7VT600", 0, it8705f_write_enable_2e}, - {0x10DE, 0x0050, 0x1458, 0x0C11, 0x10DE, 0x005e, 0x1458, 0x5000, NULL, NULL, "GIGABYTE", "GA-K8N-SLI", 0, nvidia_mcp_gpio21_raise}, - {0x10DE, 0x0360, 0x1458, 0x0C11, 0x10DE, 0x0369, 0x1458, 0x5001, "gigabyte", "m57sli", "GIGABYTE", "GA-M57SLI-S4", 0, it87xx_probe_spi_flash}, - {0x10de, 0x03e0, 0, 0, 0x10DE, 0x03D0, 0, 0, NULL, NULL, "GIGABYTE", "GA-M61P-S3", 0, it87xx_probe_spi_flash}, - {0x1002, 0x4398, 0x1458, 0x5004, 0x1002, 0x4391, 0x1458, 0xb000, NULL, NULL, "GIGABYTE", "GA-MA78G-DS3H", 0, it87xx_probe_spi_flash}, - {0x1002, 0x4398, 0x1458, 0x5004, 0x1002, 0x4391, 0x1458, 0xb002, NULL, NULL, "GIGABYTE", "GA-MA78GM-S2H", 0, it87xx_probe_spi_flash}, - {0x1002, 0x438d, 0x1458, 0x5001, 0x1002, 0x5956, 0x1002, 0x5956, NULL, NULL, "GIGABYTE", "GA-MA790FX-DQ6", 0, it87xx_probe_spi_flash}, - {0x1166, 0x0223, 0x103c, 0x320d, 0x102b, 0x0522, 0x103c, 0x31fa, "hp", "dl145_g3", "HP", "DL145 G3", 0, board_hp_dl145_g3_enable}, - {0x1166, 0x0205, 0x1014, 0x0347, 0x1002, 0x515E, 0x1014, 0x0325, NULL, NULL, "IBM", "x3455", 0, board_ibm_x3455}, - {0x1039, 0x5513, 0x8086, 0xd61f, 0x1039, 0x6330, 0x8086, 0xd61f, NULL, NULL, "Intel", "D201GLY", 0, wbsio_check_for_spi}, - {0x1022, 0x7468, 0, 0, 0, 0, 0, 0, "iwill", "dk8_htx", "IWILL", "DK8-HTX", 0, w83627hf_gpio24_raise_2e}, - {0x8086, 0x27A0, 0, 0, 0x8086, 0x27b8, 0, 0, "kontron", "986lcd-m", "Kontron", "986LCD-M", 0, board_kontron_986lcd_m}, - {0x8086, 0x2411, 0x8086, 0x2411, 0x8086, 0x7125, 0x0e11, 0xb165, NULL, NULL, "Mitac", "6513WU", 0, board_mitac_6513wu}, - {0x13f6, 0x0111, 0x1462, 0x5900, 0x1106, 0x3177, 0x1106, 0, NULL, NULL, "MSI", "MS-6590 (KT4 Ultra)", 0, board_msi_kt4v}, - {0x1106, 0x3149, 0x1462, 0x7094, 0x10ec, 0x8167, 0x1462, 0x094c, NULL, NULL, "MSI", "MS-6702E (K8T Neo2-F)", 0, w83627thf_gpio4_4_raise_2e}, - {0x1106, 0x0571, 0x1462, 0x7120, 0x1106, 0x3065, 0x1462, 0x7120, NULL, NULL, "MSI", "MS-6712 (KT4V)", 0, board_msi_kt4v}, - {0x1039, 0x7012, 0x1462, 0x0050, 0x1039, 0x6325, 0x1462, 0x0058, NULL, NULL, "MSI", "MS-7005 (651M-L)", 0, board_msi_651ml}, - {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, NULL, NULL, "MSI", "MS-7046", 0, intel_ich_gpio19_raise}, - {0x10DE, 0x005E, 0x1462, 0x7135, 0x10DE, 0x0050, 0x1462, 0x7135, "msi", "k8n-neo3", "MSI", "MS-7135 (K8N Neo3)", 0, w83627thf_gpio4_4_raise_4e}, - {0x10DE, 0x005E, 0x1462, 0x7125, 0x10DE, 0x0052, 0x1462, 0x7125, NULL, NULL, "MSI", "K8N Neo4-F", 0, nvidia_mcp_gpio2_raise}, - {0x1106, 0x3099, 0, 0, 0x1106, 0x3074, 0, 0, "shuttle", "ak31", "Shuttle", "AK31", 0, w836xx_memw_enable_2e}, - {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, "Shuttle", "AK38N", 256, it8705f_write_enable_2e}, - {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, NULL, NULL, "Shuttle", "FN25", 0, board_shuttle_fn25}, - {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, NULL, NULL, "Soyo", "SY-7VCA", 0, board_soyo_sy_7vca}, - {0x8086, 0x1076, 0x8086, 0x1176, 0x1106, 0x3059, 0x10f1, 0x2498, NULL, NULL, "Tyan", "S2498 (Tomcat K7M)", 0, w836xx_memw_enable_2e}, - {0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, NULL, NULL, "VIA", "EPIA M/MII/...", 0, via_vt823x_gpio15_raise}, - {0x1106, 0x0259, 0x1106, 0x3227, 0x1106, 0x3065, 0x1106, 0x3149, NULL, NULL, "VIA", "EPIA-N/NL", 0, via_vt823x_gpio9_raise}, - {0x1106, 0x5337, 0x1458, 0xb003, 0x1106, 0x287e, 0x1106, 0x337e, NULL, NULL, "VIA", "PC3500G", 0, it87xx_probe_spi_flash}, - - { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, 0, NULL}, /* end marker */ + /* first pci-id set [4], second pci-id set [4], superio, coreboot id [2], vendor name board name max_rom_... flash enable */ + {0x8086, 0x2926, 0x147b, 0x1084, 0x11ab, 0x4364, 0x147b, 0x1084, WB_W83627DHG, NULL, NULL, "Abit", "IP35", 0, intel_ich_gpio16_raise}, + {0x105a, 0x0d30, 0x105a, 0x4d33, 0x8086, 0x1130, 0x8086, 0, WB_W83627HF, NULL, NULL, "Acorp", "6A815EPD", 0, board_acorp_6a815epd}, + {0x8086, 0x24D4, 0x1849, 0x24D0, 0x8086, 0x24D5, 0x1849, 0x9739, WB_W83627HF, NULL, NULL, "ASRock", "P4i65GV", 0, intel_ich_gpio23_raise}, + {0x1022, 0x746B, 0, 0, 0, 0, 0, 0, WB_W83627HF, "AGAMI", "ARUMA", "agami", "Aruma", 0, w83627hf_gpio24_raise}, + {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, SIO_NONE, "artecgroup", "dbe61", "Artec Group", "DBE61", 0, board_artecgroup_dbe6x}, + {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, SIO_NONE, "artecgroup", "dbe62", "Artec Group", "DBE62", 0, board_artecgroup_dbe6x}, + {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3065, 0x1043, 0x80ED, ITE_IT8712, NULL, NULL, "ASUS", "A7V600-X", 0, board_asus_a7v600x}, + {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x808C, ITE_IT8703, NULL, NULL, "ASUS", "A7V8X", 0, board_asus_a7v8x}, + {0x1106, 0x1336, 0x1043, 0x80ed, 0x1106, 0x3288, 0x1043, 0x8249, ITE_IT8716, NULL, NULL, "ASUS", "M2V-MX", 0, via_vt823x_gpio5_raise}, + {0x8086, 0x1a30, 0x1043, 0x8070, 0x8086, 0x244b, 0x1043, 0x8028, ITE_IT8708, NULL, NULL, "ASUS", "P4B266", 0, intel_ich_gpio22_raise}, + {0x8086, 0x1A30, 0x1043, 0x8025, 0x8086, 0x244B, 0x104D, 0x80F0, SIO_UNKNOWN, NULL, NULL, "ASUS", "P4B266-LM", 0, intel_ich_gpio21_raise}, + {0x8086, 0x2570, 0x1043, 0x80F2, 0x105A, 0x3373, 0x1043, 0x80F5, WB_W83627THF, NULL, NULL, "ASUS", "P4P800-E Deluxe", 0, intel_ich_gpio21_raise}, + {0x10B9, 0x1541, 0, 0, 0x10B9, 0x1533, 0, 0, SIO_UNKNOWN, "asus", "p5a", "ASUS", "P5A", 0, board_asus_p5a}, + {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, SIO_UNKNOWN, NULL, NULL, "ASUS", "P5ND2-SLI Deluxe", 0, nvidia_mcp_gpio10_raise}, + {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, SIO_UNKNOWN, NULL, NULL, "Dell", "PowerEdge 1850", 0, intel_ich_gpio23_raise}, + {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, SIO_UNKNOWN, NULL, NULL, "Elitegroup", "K7VTA3", 256, NULL}, + {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, SIO_UNKNOWN, NULL, NULL, "EPoX", "EP-8RDA3+", 0, nvidia_mcp_gpio31_raise}, + {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, SIO_UNKNOWN, "epox", "ep-bx3", "EPoX", "EP-BX3", 0, board_epox_ep_bx3}, + {0x10DE, 0x0050, 0x1458, 0x0C11, 0x10DE, 0x005e, 0x1458, 0x5000, SIO_UNKNOWN, NULL, NULL, "GIGABYTE", "GA-K8N-SLI", 0, nvidia_mcp_gpio21_raise}, + {0x1166, 0x0223, 0x103c, 0x320d, 0x102b, 0x0522, 0x103c, 0x31fa, SIO_UNKNOWN, "hp", "dl145_g3", "HP", "DL145 G3", 0, board_hp_dl145_g3_enable}, + {0x1166, 0x0205, 0x1014, 0x0347, 0x1002, 0x515E, 0x1014, 0x0325, SIO_UNKNOWN, NULL, NULL, "IBM", "x3455", 0, board_ibm_x3455}, + {0x1022, 0x7468, 0, 0, 0, 0, 0, 0, WB_W83627HF, "iwill", "dk8_htx", "IWILL", "DK8-HTX", 0, w83627hf_gpio24_raise}, + {0x8086, 0x27A0, 0, 0, 0x8086, 0x27b8, 0, 0, SIO_UNKNOWN, "kontron", "986lcd-m", "Kontron", "986LCD-M", 0, board_kontron_986lcd_m}, + {0x8086, 0x2411, 0x8086, 0x2411, 0x8086, 0x7125, 0x0e11, 0xb165, SIO_UNKNOWN, NULL, NULL, "Mitac", "6513WU", 0, board_mitac_6513wu}, + {0x13f6, 0x0111, 0x1462, 0x5900, 0x1106, 0x3177, 0x1106, 0, WB_W83697HF, NULL, NULL, "MSI", "MS-6590 (KT4 Ultra)", 0, via_vt823x_gpio12_raise}, + {0x1106, 0x3149, 0x1462, 0x7094, 0x10ec, 0x8167, 0x1462, 0x094c, WB_W83627THF, NULL, NULL, "MSI", "MS-6702E (K8T Neo2-F)", 0, w83627thf_gpio44_raise}, + {0x1106, 0x0571, 0x1462, 0x7120, 0x1106, 0x3065, 0x1462, 0x7120, WB_W83697HF, NULL, NULL, "MSI", "MS-6712 (KT4V)", 0, via_vt823x_gpio12_raise}, + {0x1039, 0x7012, 0x1462, 0x0050, 0x1039, 0x6325, 0x1462, 0x0058, WB_W83697HF, NULL, NULL, "MSI", "MS-7005 (651M-L)", 0, board_msi_651ml}, + {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, SIO_UNKNOWN, NULL, NULL, "MSI", "MS-7046", 0, intel_ich_gpio19_raise}, + {0x10DE, 0x005E, 0x1462, 0x7135, 0x10DE, 0x0050, 0x1462, 0x7135, WB_W83627THF, "msi", "k8n-neo3", "MSI", "MS-7135 (K8N Neo3)", 0, w83627thf_gpio44_raise}, + {0x10DE, 0x005E, 0x1462, 0x7125, 0x10DE, 0x0052, 0x1462, 0x7125, SIO_UNKNOWN, NULL, NULL, "MSI", "K8N Neo4-F", 0, nvidia_mcp_gpio2_raise}, + {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, SIO_UNKNOWN, NULL, NULL, "Shuttle", "AK38N", 256, NULL}, + {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, SIO_UNKNOWN, NULL, NULL, "Shuttle", "FN25", 0, board_shuttle_fn25}, + {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, SIO_UNKNOWN, NULL, NULL, "Soyo", "SY-7VCA", 0, board_soyo_sy_7vca}, + {0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, VIA_VT1211, NULL, NULL, "VIA", "EPIA M/MII/...", 0, via_vt823x_gpio15_raise}, + {0x1106, 0x0259, 0x1106, 0x3227, 0x1106, 0x3065, 0x1106, 0x3149, SIO_UNKNOWN, NULL, NULL, "VIA", "EPIA-N/NL", 0, via_vt823x_gpio9_raise}, + + { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, 0, NULL}, /* end marker */ }; /** diff --git a/chipset_enable.c b/chipset_enable.c index f106f96..e06562a 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -33,6 +33,7 @@ #include <sys/stat.h> #include <fcntl.h> #include "flash.h" +#include "superio.h" extern int ichspi_lock; diff --git a/flash.h b/flash.h index 75a84b0..1b1eb72 100644 --- a/flash.h +++ b/flash.h @@ -55,9 +55,6 @@ enum programmer { #if SATASII_SUPPORT == 1 PROGRAMMER_SATASII, #endif -#if INTERNAL_SUPPORT == 1 - PROGRAMMER_IT87SPI, -#endif #if FT2232_SPI_SUPPORT == 1 PROGRAMMER_FT2232SPI, #endif @@ -262,6 +259,8 @@ struct board_pciid_enable { uint16_t second_card_vendor; uint16_t second_card_device; + int superio; /* enum superio_chip */ + /* The vendor / part name from the coreboot table. */ const char *lb_vendor; const char *lb_part; @@ -319,12 +318,16 @@ void print_supported_pcidevs(struct pcidev_status *devs); #endif void print_supported_wiki(void); +#if 0 /* board_enable.c */ void w836xx_ext_enter(uint16_t port); void w836xx_ext_leave(uint16_t port); uint8_t sio_read(uint16_t port, uint8_t reg); void sio_write(uint16_t port, uint8_t reg, uint8_t data); void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask); +#endif + +/* board enable.c */ int board_flash_enable(const char *vendor, const char *part); /* chipset_enable.c */ @@ -344,14 +347,6 @@ extern int partvendor_from_cbtable; /* internal.c */ #if NEED_PCI == 1 -struct superio { - uint16_t vendor; - uint16_t port; - uint16_t model; -}; -extern struct superio superio; -#define SUPERIO_VENDOR_NONE 0x0 -#define SUPERIO_VENDOR_ITE 0x1 struct pci_dev *pci_dev_find_filter(struct pci_filter filter); struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class); struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device); @@ -361,7 +356,6 @@ struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, void get_io_perms(void); void release_io_perms(void); #if INTERNAL_SUPPORT == 1 -void probe_superio(void); int internal_init(void); int internal_shutdown(void); void internal_chip_writeb(uint8_t val, chipaddr addr); @@ -593,18 +587,6 @@ int ich_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int ich_spi_write_256(struct flashchip *flash, uint8_t * buf); int ich_spi_send_multicommand(struct spi_command *cmds); -/* it87spi.c */ -extern uint16_t it8716f_flashport; -void enter_conf_mode_ite(uint16_t port); -void exit_conf_mode_ite(uint16_t port); -struct superio probe_superio_ite(void); -int it87spi_init(void); -int it87xx_probe_spi_flash(const char *name); -int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr); -int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len); -int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf); - /* sb600spi.c */ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); @@ -612,13 +594,6 @@ int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf); extern uint8_t *sb600_spibar; -/* wbsio_spi.c */ -int wbsio_check_for_spi(const char *name); -int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr); -int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); -int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf); - /* serprog.c */ int serprog_init(void); int serprog_shutdown(void); diff --git a/flashrom.c b/flashrom.c index db44c2f..1f8979b 100644 --- a/flashrom.c +++ b/flashrom.c @@ -207,25 +207,6 @@ const struct programmer_entry programmer_table[] = { }, #endif -#if INTERNAL_SUPPORT == 1 - { - .name = "it87spi", - .init = it87spi_init, - .shutdown = noop_shutdown, - .map_flash_region = fallback_map, - .unmap_flash_region = fallback_unmap, - .chip_readb = noop_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, - .chip_writeb = noop_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, - .delay = internal_delay, - }, -#endif - #if FT2232_SPI_SUPPORT == 1 { .name = "ft2232spi", diff --git a/internal.c b/internal.c index acb99b7..a545892 100644 --- a/internal.c +++ b/internal.c @@ -27,6 +27,8 @@ #include <errno.h> #include "flash.h" +#include "superio.h" + #if defined(__FreeBSD__) || defined(__DragonFly__) int io_fd; #endif @@ -125,17 +127,6 @@ void release_io_perms(void) } #if INTERNAL_SUPPORT == 1 -struct superio superio = {}; - -void probe_superio(void) -{ - superio = probe_superio_ite(); -#if 0 /* Winbond SuperI/O code is not yet available. */ - if (superio.vendor == SUPERIO_VENDOR_NONE) - superio = probe_superio_winbond(); -#endif -} - int internal_init(void) { int ret = 0; @@ -153,9 +144,6 @@ int internal_init(void) */ coreboot_init(); - /* Probe for the SuperI/O chip and fill global struct superio. */ - probe_superio(); - /* try to enable it. Failure IS an option, since not all motherboards * really need this to be done, etc., etc. */ @@ -165,6 +153,10 @@ int internal_init(void) "will most likely fail.\n"); } + /* Probe for the SuperI/O chip and fill global struct superio. */ + superio_probe(); + superio_init(); + board_flash_enable(lb_vendor, lb_part); /* Even if chipset init returns an error code, we don't want to abort. diff --git a/it87spi.c b/it87spi.c index fcbf086..c8a8fc6 100644 --- a/it87spi.c +++ b/it87spi.c @@ -27,167 +27,29 @@ #include <stdlib.h> #include "flash.h" #include "spi.h" +#include "superio.h" -#define ITE_SUPERIO_PORT1 0x2e -#define ITE_SUPERIO_PORT2 0x4e - -uint16_t it8716f_flashport = 0; +static uint16_t flashport = 0; /* use fast 33MHz SPI (<>0) or slow 16MHz (0) */ -int fast_spi = 1; - -/* Helper functions for most recent ITE IT87xx Super I/O chips */ -#define CHIP_ID_BYTE1_REG 0x20 -#define CHIP_ID_BYTE2_REG 0x21 -void enter_conf_mode_ite(uint16_t port) -{ - OUTB(0x87, port); - OUTB(0x01, port); - OUTB(0x55, port); - if (port == ITE_SUPERIO_PORT1) - OUTB(0x55, port); - else - OUTB(0xaa, port); -} +static int fast_spi = 1; -void exit_conf_mode_ite(uint16_t port) +int it8716_spi_init(uint16_t port) { - sio_write(port, 0x02, 0x02); -} + ite_conf_mode_enter(port); -uint16_t probe_id_ite(uint16_t port) -{ - uint16_t id; - - enter_conf_mode_ite(port); - id = sio_read(port, CHIP_ID_BYTE1_REG) << 8; - id |= sio_read(port, CHIP_ID_BYTE2_REG); - exit_conf_mode_ite(port); - - return id; -} - -struct superio probe_superio_ite(void) -{ - struct superio ret = {}; - uint16_t ite_ports[] = {ITE_SUPERIO_PORT1, ITE_SUPERIO_PORT2, 0}; - uint16_t *i = ite_ports; - - ret.vendor = SUPERIO_VENDOR_ITE; - for (; *i; i++) { - ret.port = *i; - ret.model = probe_id_ite(ret.port); - switch (ret.model >> 8) { - case 0x82: - case 0x86: - case 0x87: - msg_pinfo("Found ITE SuperI/O, id %04hx\n", - ret.model); - return ret; - } - } - - /* No good ID found. */ - ret.vendor = SUPERIO_VENDOR_NONE; - ret.port = 0; - ret.model = 0; - return ret; -} - -static uint16_t find_ite_spi_flash_port(uint16_t port, uint16_t id) -{ - uint8_t tmp = 0; - char *portpos = NULL; - uint16_t flashport = 0; - - switch (id) { - case 0x8716: - case 0x8718: - enter_conf_mode_ite(port); - /* NOLDN, reg 0x24, mask out lowest bit (suspend) */ - tmp = sio_read(port, 0x24) & 0xFE; - msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n", - 0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis"); - msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n", - 0x000E0000, 0x000FFFFF, (tmp & 1 << 1) ? "en" : "dis"); - msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n", - 0xFFEE0000, 0xFFEFFFFF, (tmp & 1 << 2) ? "en" : "dis"); - msg_pdbg("Serial flash segment 0x%08x-0x%08x %sabled\n", - 0xFFF80000, 0xFFFEFFFF, (tmp & 1 << 3) ? "en" : "dis"); - msg_pdbg("LPC write to serial flash %sabled\n", - (tmp & 1 << 4) ? "en" : "dis"); - /* The LPC->SPI force write enable below only makes sense for - * non-programmer mode. - */ - /* If any serial flash segment is enabled, enable writing. */ - if ((tmp & 0xe) && (!(tmp & 1 << 4))) { - msg_pdbg("Enabling LPC write to serial flash\n"); - tmp |= 1 << 4; - sio_write(port, 0x24, tmp); - } - msg_pdbg("Serial flash pin %i\n", (tmp & 1 << 5) ? 87 : 29); + if (sio_read(port, 0x24) & 0x10) { /* LDN 0x7, reg 0x64/0x65 */ sio_write(port, 0x07, 0x7); flashport = sio_read(port, 0x64) << 8; flashport |= sio_read(port, 0x65); - msg_pdbg("Serial flash port 0x%04x\n", flashport); - if (programmer_param && !strlen(programmer_param)) { - free(programmer_param); - programmer_param = NULL; - } - if (programmer_param && (portpos = strstr(programmer_param, "port="))) { - portpos += 5; - flashport = strtol(portpos, (char **)NULL, 0); - msg_pinfo("Forcing serial flash port 0x%04x\n", flashport); - sio_write(port, 0x64, (flashport >> 8)); - sio_write(port, 0x65, (flashport & 0xff)); - } - exit_conf_mode_ite(port); - break; - /* TODO: Handle more IT87xx if they support flash translation */ - default: - msg_pinfo("SuperI/O ID %04hx is not on the controller list.\n", id); - } - return flashport; -} - -int it87spi_common_init(void) -{ - if (superio.vendor != SUPERIO_VENDOR_ITE) - return 1; - - it8716f_flashport = find_ite_spi_flash_port(superio.port, superio.model); - - if (it8716f_flashport) - spi_controller = SPI_CONTROLLER_IT87XX; - - return (!it8716f_flashport); -} - -int it87spi_init(void) -{ - int ret; - - get_io_perms(); - /* Probe for the SuperI/O chip and fill global struct superio. */ - probe_superio(); - ret = it87spi_common_init(); - if (!ret) { - buses_supported = CHIP_BUSTYPE_SPI; - } else { - buses_supported = CHIP_BUSTYPE_NONE; + if (flashport) { + spi_controller = SPI_CONTROLLER_IT87XX; + buses_supported = CHIP_BUSTYPE_SPI; + } } - return ret; -} -int it87xx_probe_spi_flash(const char *name) -{ - int ret; - - ret = it87spi_common_init(); - if (!ret) - buses_supported |= CHIP_BUSTYPE_SPI; - return ret; + return 0; } /* @@ -206,7 +68,7 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, int i; do { - busy = INB(it8716f_flashport) & 0x80; + busy = INB(flashport) & 0x80; } while (busy); if (readcnt > 3) { msg_pinfo("%s called with unsupported readcnt %i.\n", @@ -215,27 +77,27 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, } switch (writecnt) { case 1: - OUTB(writearr[0], it8716f_flashport + 1); + OUTB(writearr[0], flashport + 1); writeenc = 0x0; break; case 2: - OUTB(writearr[0], it8716f_flashport + 1); - OUTB(writearr[1], it8716f_flashport + 7); + OUTB(writearr[0], flashport + 1); + OUTB(writearr[1], flashport + 7); writeenc = 0x1; break; case 4: - OUTB(writearr[0], it8716f_flashport + 1); - OUTB(writearr[1], it8716f_flashport + 4); - OUTB(writearr[2], it8716f_flashport + 3); - OUTB(writearr[3], it8716f_flashport + 2); + OUTB(writearr[0], flashport + 1); + OUTB(writearr[1], flashport + 4); + OUTB(writearr[2], flashport + 3); + OUTB(writearr[3], flashport + 2); writeenc = 0x2; break; case 5: - OUTB(writearr[0], it8716f_flashport + 1); - OUTB(writearr[1], it8716f_flashport + 4); - OUTB(writearr[2], it8716f_flashport + 3); - OUTB(writearr[3], it8716f_flashport + 2); - OUTB(writearr[4], it8716f_flashport + 7); + OUTB(writearr[0], flashport + 1); + OUTB(writearr[1], flashport + 4); + OUTB(writearr[2], flashport + 3); + OUTB(writearr[3], flashport + 2); + OUTB(writearr[4], flashport + 7); writeenc = 0x3; break; default: @@ -249,15 +111,15 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, * We can't use writecnt directly, but have to use a strange encoding. */ OUTB(((0x4 + (fast_spi ? 1 : 0)) << 4) - | ((readcnt & 0x3) << 2) | (writeenc), it8716f_flashport); + | ((readcnt & 0x3) << 2) | (writeenc), flashport); if (readcnt > 0) { do { - busy = INB(it8716f_flashport) & 0x80; + busy = INB(flashport) & 0x80; } while (busy); for (i = 0; i < readcnt; i++) - readarr[i] = INB(it8716f_flashport + 5 + i); + readarr[i] = INB(flashport + 5 + i); } return 0; @@ -274,12 +136,12 @@ static int it8716f_spi_page_program(struct flashchip *flash, int block, uint8_t if (result) return result; /* FIXME: The command below seems to be redundant or wrong. */ - OUTB(0x06, it8716f_flashport + 1); - OUTB(((2 + (fast_spi ? 1 : 0)) << 4), it8716f_flashport); + OUTB(0x06, flashport + 1); + OUTB(((2 + (fast_spi ? 1 : 0)) << 4), flashport); for (i = 0; i < 256; i++) { chip_writeb(buf[256 * block + i], bios + 256 * block + i); } - OUTB(0, it8716f_flashport); + OUTB(0, flashport); /* Wait until the Write-In-Progress bit is cleared. * This usually takes 1-10 ms, so wait in 1 ms steps. */ @@ -297,7 +159,7 @@ int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int int total_size = 1024 * flash->total_size; fast_spi = 0; - if ((programmer == PROGRAMMER_IT87SPI) || (total_size > 512 * 1024)) { + if (total_size > 512 * 1024) { spi_read_chunked(flash, buf, start, len, 3); } else { read_memmapped(flash, buf, start, len); @@ -315,7 +177,7 @@ int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf) * IT8716F only allows maximum of 512 kb SPI chip size for memory * mapped access. */ - if ((programmer == PROGRAMMER_IT87SPI) || (total_size > 512 * 1024)) { + if (total_size > 512 * 1024) { spi_chip_write_1(flash, buf); } else { spi_disable_blockprotect(); diff --git a/spi.c b/spi.c index 43dc4bf..d85fc14 100644 --- a/spi.c +++ b/spi.c @@ -26,6 +26,7 @@ #include "flash.h" #include "flashchips.h" #include "spi.h" +#include "superio.h" /* for it87spi and wbsio */ enum spi_controller spi_controller = SPI_CONTROLLER_NONE; void *spibar = NULL; diff --git a/superio.c b/superio.c new file mode 100644 index 0000000..4647321 --- /dev/null +++ b/superio.c @@ -0,0 +1,454 @@ +/* + * This file is part of the flashrom project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> +#include <stdint.h> + + +#include "hwaccess.h" + +#include "flash.h" /* GRR! */ + +#include "superio.h" + +/* Preset global variables. */ +struct superio *superio = NULL; +uint16_t superio_port = 0; + +#include "flash.h" + +/** + * + */ +char *superio_chip_name(enum superio_chip chip) +{ + struct { + enum superio_chip chip; + char *name; + } superio_chip_name[] = { + {ITE_IT8703, "ITE IT8703"}, + {ITE_IT8705, "ITE IT8705"}, + {ITE_IT8712, "ITE IT8712"}, + {ITE_IT8716, "ITE IT8716"}, + {ITE_IT8718, "ITE IT8718"}, + {VIA_VT1211, "VIA VT1211"}, + {WB_W83627DHG, "Winbond W83627DHG"}, + {WB_W83627EHF, "Winbond W83627EHF/EF/EHG/EG"}, + {WB_W83627HF, "Winbond W83627HF"}, + {WB_W83627THF, "Winbond W83627THF"}, + {WB_W83697HF, "Winbond W83697HF"}, + {SIO_NONE, NULL}, + }; + int i; + + for (i = 0; superio_chip_name[i].name; i++) + if (superio_chip_name[i].chip == chip) + return superio_chip_name[i].name; + + return "Unknown"; +} + +/* Generic Super I/O helper functions */ +uint8_t +sio_read(uint16_t port, uint8_t reg) +{ + OUTB(reg, port); + return INB(port + 1); +} + +void +sio_write(uint16_t port, uint8_t reg, uint8_t data) +{ + OUTB(reg, port); + OUTB(data, port + 1); +} + +void +sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask) +{ + uint8_t tmp; + + OUTB(reg, port); + tmp = INB(port + 1) & ~mask; + OUTB(tmp | (data & mask), port + 1); +} + +/* + * Helper functions for many Winbond Super I/Os of the W836xx range. + */ +/* Enter extended functions */ +void +w836xx_ext_enter(uint16_t port) +{ + OUTB(0x87, port); + OUTB(0x87, port); +} + +/* Leave extended functions */ +void +w836xx_ext_leave(uint16_t port) +{ + OUTB(0xAA, port); +} + +/** + * + */ +static uint16_t +w836xx_detect(uint16_t port) +{ + uint16_t id; + + w836xx_ext_enter(port); + id = sio_read(port, 0x20); + w836xx_ext_leave(port); + + return id; +} + +/** + * Only sets gpio24 for now. + */ +static int +w83627hf_gpio_set(uint16_t port, int gpio, int raise) +{ + if (gpio != 24) { + fprintf(stderr, "\nERROR: Only gpio24 is supported.\n"); + return 1; + } + + + w836xx_ext_enter(port); + + /* PIN89S: WDTO/GP24 multiplex -> GPIO24 */ + sio_mask(port, 0x2B, 0x10, 0x10); + + /* Select logical device 8: GPIO port 2 */ + sio_write(port, 0x07, 0x08); + + sio_mask(port, 0x30, 0x01, 0x01); /* Activate logical device. */ + sio_mask(port, 0xF0, 0x00, 0x10); /* GPIO24 -> output */ + sio_mask(port, 0xF2, 0x00, 0x10); /* Clear GPIO24 inversion */ + + if (raise) + sio_mask(port, 0xF1, 0x10, 0x10); + else + sio_mask(port, 0xF1, 0, 0x10); + + w836xx_ext_leave(port); + + return 0; +} + +/** + * Only raises gpio44 for now. + */ +static int +w83627thf_gpio_set(uint16_t port, int gpio, int raise) +{ + if (gpio != 44) { + fprintf(stderr, "\nERROR: Only gpio44 is supported.\n"); + return 1; + } + + w836xx_ext_enter(port); + + /* PINxxxxS: GPIO4/bit 4 multiplex -> GPIOXXX */ + + sio_write(port, 0x07, 0x09); /* Select LDN 9: GPIO port 4 */ + sio_mask(port, 0x30, 0x02, 0x02); /* Activate logical device. */ + sio_mask(port, 0xF4, 0x00, 0x10); /* GPIO4 bit 4 -> output */ + sio_mask(port, 0xF6, 0x00, 0x10); /* Clear GPIO4 bit 4 inversion */ + sio_mask(port, 0xF5, 0x10, 0x10); /* Raise GPIO4 bit 4 */ + + w836xx_ext_leave(port); + + return 0; +} + +#if 0 +/** + * w83697hf: Enable MEMW# and set ROM size to max. + */ +static int +w83697hf_memw_enable(uint16_t port) +{ + w836xx_ext_enter(port); + if (!(sio_read(port, 0x24) & 0x02)) { /* Flash ROM enabled? */ + /* Enable MEMW# and set ROM size select to max. (4M). */ + sio_mask(port, 0x24, 0x28, 0x28); + } + w836xx_ext_leave(port); + + return 0; +} +#endif + +/* + * + * ITE functions. + * + */ + +/** + * + */ +void +ite_conf_mode_enter(uint16_t port) +{ + OUTB(0x87, port); + OUTB(0x01, port); + OUTB(0x55, port); + if (port == 0x2E) + OUTB(0x55, port); + else + OUTB(0xaa, port); +} + +/** + * + */ +void +ite_conf_mode_exit(uint16_t port) +{ + sio_write(port, 0x02, 0x02); +} + +/** + * + */ +static uint16_t +it87xx_detect(uint16_t port) +{ + uint16_t id; + + ite_conf_mode_enter(port); + id = (sio_read(port, 0x20) << 8) | sio_read(port, 0x21); + ite_conf_mode_exit(port); + + return id; +} + +/** + * + */ +static int +it8705f_write_enable(uint16_t port) +{ + ite_conf_mode_enter(port); + sio_mask(port, 0x24, 0x04, 0x04); /* Flash ROM I/F Writes Enable */ + ite_conf_mode_exit(port); + + return 0; +} + +/** + * Only raises gpio51 for now. + */ +static int +it8703_gpio_set(uint16_t port, int gpio, int raise) +{ + uint16_t base; + uint8_t tmp; + + if (gpio != 51) { + fprintf(stderr, "\nERROR: Only gpio51 is supported.\n"); + return -1; + } + + /* Get the GP567 IO base */ + w836xx_ext_enter(port); + sio_write(port, 0x07, 0x0C); + base = (sio_read(port, 0x60) << 8) | sio_read(port, 0x61); + w836xx_ext_leave(port); + + if (!base) { + fprintf(stderr, "\nERROR: Failed to read IT8703F SuperIO GPIO" + " Base.\n"); + return -1; + } + + /* Raise GP51. */ + tmp = INB(base); + if (raise) + tmp |= 0x02; + else + tmp &= ~0x02; + OUTB(tmp, base); + + return 0; +} + +/* + * General routine for raising/dropping GPIO lines on the ITE IT8712F. + * There is only some limited checking on the port numbers. + */ +static int +it8712f_gpio_set(uint16_t port, int gpio, int raise) +{ + unsigned int block; + uint16_t base; + uint8_t tmp; + + block = gpio / 10; + block--; + gpio %= 10; + + /* Check gpio */ + if ((block > 4) || /* also catches unsigned -1 */ + ((block < 4) && (gpio > 7)) || ((block == 4) && (gpio > 5))) { + fprintf(stderr, + "\nERROR: Unsupported IT8712F GPIO %02d.\n", gpio); + return -1; + } + + /* Get the GPIO base */ + ite_conf_mode_enter(port); + sio_write(port, 0x07, 0x07); + base = (sio_read(port, 0x62) << 8) | sio_read(port, 0x63); + ite_conf_mode_exit(port); + + if (!base) { + fprintf(stderr, "\nERROR: Failed to read IT8712F SuperIO GPIO" + " Base.\n"); + return -1; + } + + /* set GPIO. */ + tmp = INB(base + block); + if (raise) + tmp |= 1 << gpio; + else + tmp &= ~(1 << gpio); + OUTB(tmp, base + block); + + return 0; +} + +/** + * + */ +static struct superio superios[] = { + {it87xx_detect, 0x8701, ITE_IT8703, NULL, it8703_gpio_set}, + {it87xx_detect, 0x8705, ITE_IT8705, it8705f_write_enable, NULL}, + {it87xx_detect, 0x8712, ITE_IT8712, NULL, it8712f_gpio_set}, + {it87xx_detect, 0x8716, ITE_IT8716, it8716_spi_init, NULL}, + {it87xx_detect, 0x8718, ITE_IT8718, it8716_spi_init, NULL}, + {w836xx_detect, 0x3C, VIA_VT1211, NULL, NULL}, + {w836xx_detect, 0x52, WB_W83627HF, NULL, w83627hf_gpio_set}, + //{w836xx_detect, 0x60, WB_W83697HF, w83697hf_memw_enable, NULL}, + {w836xx_detect, 0x82, WB_W83627THF, NULL, w83627thf_gpio_set}, + {w836xx_detect, 0x88, WB_W83627EHF, NULL, NULL}, + {w836xx_detect, 0xA0, WB_W83627DHG, w83627dhg_spi_init, NULL}, + + {NULL, 0, SIO_NONE, NULL, NULL} /* end marker */ +}; + +/* + * + * High level routines. + * + */ + +/* + * + */ +int +superio_probe(void) +{ + struct superio_detect { + uint16_t port; + uint16_t (*detect) (uint16_t port); + char *name; + } superio_detects[] = { + {0x2E, w836xx_detect, "Winbond W836xx"}, + {0x4E, w836xx_detect, "Winbond W836xx"}, + {0x2E, it87xx_detect, "ITE IT87xx"}, + {0x4E, it87xx_detect, "ITE IT87xx"}, + + {0, NULL} /* end marker */ + }; + + int i, j; + uint16_t id; + + for (i = 0; superio_detects[i].detect; i++) { + + id = superio_detects[i].detect(superio_detects[i].port); + if ((id == 0xFF) || (id == 0xFFFF)) + continue; + + msg_pdbg("Superio detection for \"%s\" on 0x%X" + " returned 0x%0X\n", superio_detects[i].name, + superio_detects[i].port, id); + + for (j = 0; superios[j].detect; j++) { + if ((superios[j].detect == superio_detects[i].detect) && + (id == superios[j].id)) { + superio = &superios[j]; + superio_port = superio_detects[i].port; + break; + } + } + + if (!superio) + msg_perr("No matching superio found for \"%s\" (0x%X) :" + " 0x%0X\n", superio_detects[i].name, + superio_detects[i].port, id); + } + + if (superio) + msg_pinfo("Superio \"%s\" detected on 0x%0X.\n", + superio_chip_name(superio->chip), superio_port); + else + msg_pdbg("No Superio chip detected.\n"); + + return 0; +} + +/* + * + */ +int +superio_init(void) +{ + if (!superio || !superio->init) + return 0; /* not an error */ + + printf("Initialising \"%s\" superio.\n", + superio_chip_name(superio->chip)); + + return superio->init(superio_port); +} + +/* + * + */ +int +superio_gpio_set(int gpio, int raise) +{ + if (!superio || !superio->gpio_set) { + printf("Error: Unable to set gpio line on superio.\n"); + return 1; + } + + printf("Setting GPIO%d(%X) on superio \"%s\" to %s\n", + gpio, gpio, superio_chip_name(superio->chip), + raise ? "high" : "low"); + + return superio->gpio_set(superio_port, gpio, raise); +} diff --git a/superio.h b/superio.h new file mode 100644 index 0000000..cc1c9ba --- /dev/null +++ b/superio.h @@ -0,0 +1,107 @@ +/* + * This file is part of the flashrom project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef HAVE_SUPERIO_H +#define HAVE_SUPERIO_H 1 + +/* + * + */ +enum superio_chip { + SIO_NONE = 0, + + /* ITE */ + ITE_IT8703, + ITE_IT8705, + ITE_IT8708, + ITE_IT8712, + ITE_IT8716, + ITE_IT8718, + + /* A lonesome VIA superio */ + VIA_VT1211, + + /* Winbond */ + WB_W83627DHG, + WB_W83627EHF, + WB_W83627HF, + WB_W83627THF, + WB_W83697HF, + + SIO_UNKNOWN +}; + +/* + * + */ +struct superio { + uint16_t (*detect) (uint16_t port); + uint16_t id; + + enum superio_chip chip; + + int (*init) (uint16_t port); + int (*gpio_set) (uint16_t port, int gpio, int raise); +}; + +struct superio *superio; +uint16_t superio_port; + +uint8_t sio_read(uint16_t port, uint8_t reg); +void sio_write(uint16_t port, uint8_t reg, uint8_t data); +void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask); + +void w836xx_ext_enter(uint16_t port); +void w836xx_ext_leave(uint16_t port); + +void ite_conf_mode_enter(uint16_t port); +void ite_conf_mode_exit(uint16_t port); + +/* + * High level calls. + */ +int superio_probe(void); +int superio_init(void); +int superio_gpio_set(int gpio, int raise); + +/* + * + * Will someone please pour the programmer infrastructure in a struct with + * callbacks that gets created by the init functions below? This lack of + * abstraction now causes us to have to include horrible flash.h before + * this file. + * + */ + +/* + * it87spi.c + */ +int it8716_spi_init(uint16_t port); +int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr); +int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len); +int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf); + +/* + * wbsio_spi.c + */ +int w83627dhg_spi_init(uint16_t port); +int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr); +int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); +int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf); + +#endif /* HAVE_SUPERIO_H */ diff --git a/wbsio_spi.c b/wbsio_spi.c index 922aff1..ac95bdd 100644 --- a/wbsio_spi.c +++ b/wbsio_spi.c @@ -21,52 +21,28 @@ #include <string.h> #include "flash.h" #include "spi.h" - -#define WBSIO_PORT1 0x2e -#define WBSIO_PORT2 0x4e +#include "superio.h" static uint16_t wbsio_spibase = 0; -static uint16_t wbsio_get_spibase(uint16_t port) +int w83627dhg_spi_init(uint16_t port) { - uint8_t id; - uint16_t flashport = 0; - w836xx_ext_enter(port); - id = sio_read(port, 0x20); - if (id != 0xa0) { - msg_perr("\nW83627 not found at 0x%x, id=0x%02x want=0xa0.\n", port, id); - goto done; - } - if (0 == (sio_read(port, 0x24) & 2)) { - msg_perr("\nW83627 found at 0x%x, but SPI pins are not enabled. (CR[0x24] bit 1=0)\n", port); - goto done; - } + if (sio_read(port, 0x24) & 0x02) { /* Are SPI pins enabled? */ + sio_write(port, 0x07, 0x06); /* LDN 6 */ + if (sio_read(port, 0x30) & 0x01) { /* SPI enabled? */ + wbsio_spibase = (sio_read(port, 0x62) << 8) | + sio_read(port, 0x63); - sio_write(port, 0x07, 0x06); - if (0 == (sio_read(port, 0x30) & 1)) { - msg_perr("\nW83627 found at 0x%x, but SPI is not enabled. (LDN6[0x30] bit 0=0)\n", port); - goto done; - } + msg_pspew("\nwbsio_spibase = 0x%x\n", wbsio_spibase); - flashport = (sio_read(port, 0x62) << 8) | sio_read(port, 0x63); + buses_supported |= CHIP_BUSTYPE_SPI; + spi_controller = SPI_CONTROLLER_WBSIO; + } + } -done: w836xx_ext_leave(port); - return flashport; -} - -int wbsio_check_for_spi(const char *name) -{ - if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT1))) - if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT2))) - return 1; - - msg_pspew("\nwbsio_spibase = 0x%x\n", wbsio_spibase); - - buses_supported |= CHIP_BUSTYPE_SPI; - spi_controller = SPI_CONTROLLER_WBSIO; return 0; } -- 1.6.0.2
_______________________________________________ flashrom mailing list flashrom@flashrom.org http://www.flashrom.org/mailman/listinfo/flashrom