summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2009-11-15 17:13:29 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2009-11-15 17:13:29 +0000
commit9f46cfca38fad1c35c02bddfaa1f5325e5cd5354 (patch)
tree78f6e15401905632b29a18e08700772a5e380f4b
parent964f27498b21177e01607bf3c20c5e3e9054b85a (diff)
downloadast2050-flashrom-9f46cfca38fad1c35c02bddfaa1f5325e5cd5354.zip
ast2050-flashrom-9f46cfca38fad1c35c02bddfaa1f5325e5cd5354.tar.gz
Add support for every single SiS chipset out there
The two existing SiS chipset enables (compared to the 28 in this patch) were refactored, and one of them was fixed. A function to match PCI vendor/class combinations was added to generic code. Tested on the "Elitegroup K7S5A". Results are somewhat unexpected (some PCI settings seem to be inaccessible, but it still works). This is not based on any docs, but rather on detailed analysis of existing opensource code for some of the chipsets. Thanks to for Adrian Glaubitz testing. Corresponding to flashrom svn r759. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
-rw-r--r--chipset_enable.c267
-rw-r--r--flash.h1
-rw-r--r--internal.c20
3 files changed, 221 insertions, 67 deletions
diff --git a/chipset_enable.c b/chipset_enable.c
index 3b3ab3d..286ab2f 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -70,54 +70,193 @@ static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name)
return 0;
}
-static int enable_flash_sis630(struct pci_dev *dev, const char *name)
+static int enable_flash_sis85c496(struct pci_dev *dev, const char *name)
+{
+ uint8_t tmp;
+
+ tmp = pci_read_byte(dev, 0xd0);
+ tmp |= 0xf8;
+ pci_write_byte(dev, 0xd0, tmp);
+
+ return 0;
+}
+
+static int enable_flash_sis_mapping(struct pci_dev *dev, const char *name)
+{
+ uint8_t new, newer;
+
+ /* Extended BIOS enable = 1, Lower BIOS Enable = 1 */
+ /* This is 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */
+ new = pci_read_byte(dev, 0x40);
+ new &= (~0x04); /* No idea why we clear bit 2. */
+ new |= 0xb; /* 0x3 for some chipsets, bit 7 seems to be don't care. */
+ pci_write_byte(dev, 0x40, new);
+ newer = pci_read_byte(dev, 0x40);
+ if (newer != new) {
+ printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
+ printf_debug("Stuck at 0x%x\n", newer);
+ return -1;
+ }
+ return 0;
+}
+
+static struct pci_dev *find_southbridge(uint16_t vendor, const char *name)
+{
+ struct pci_dev *sbdev;
+
+ sbdev = pci_dev_find_vendorclass(vendor, 0x0601);
+ if (!sbdev)
+ sbdev = pci_dev_find_vendorclass(vendor, 0x0680);
+ if (!sbdev)
+ sbdev = pci_dev_find_vendorclass(vendor, 0x0000);
+ if (!sbdev)
+ fprintf(stderr, "No southbridge found for %s!\n", name);
+ if (sbdev)
+ printf_debug("Found southbridge %04x:%04x at %02x:%02x:%01x\n",
+ sbdev->vendor_id, sbdev->device_id,
+ sbdev->bus, sbdev->dev, sbdev->func);
+ return sbdev;
+}
+
+static int enable_flash_sis501(struct pci_dev *dev, const char *name)
+{
+ uint8_t tmp;
+ int ret = 0;
+ struct pci_dev *sbdev;
+
+ sbdev = find_southbridge(dev->vendor_id, name);
+ if (!sbdev)
+ return -1;
+
+ ret = enable_flash_sis_mapping(sbdev, name);
+
+ tmp = sio_read(0x22, 0x80);
+ tmp &= (~0x20);
+ tmp |= 0x4;
+ sio_write(0x22, 0x80, tmp);
+
+ tmp = sio_read(0x22, 0x70);
+ tmp &= (~0x20);
+ tmp |= 0x4;
+ sio_write(0x22, 0x70, tmp);
+
+ return ret;
+}
+
+static int enable_flash_sis5511(struct pci_dev *dev, const char *name)
+{
+ uint8_t tmp;
+ int ret = 0;
+ struct pci_dev *sbdev;
+
+ sbdev = find_southbridge(dev->vendor_id, name);
+ if (!sbdev)
+ return -1;
+
+ ret = enable_flash_sis_mapping(sbdev, name);
+
+ tmp = sio_read(0x22, 0x50);
+ tmp &= (~0x20);
+ tmp |= 0x4;
+ sio_write(0x22, 0x50, tmp);
+
+ return ret;
+}
+
+static int enable_flash_sis5596(struct pci_dev *dev, const char *name)
+{
+ int ret;
+
+ ret = enable_flash_sis5511(dev, name);
+
+ /* FIXME: Needs same superio handling as enable_flash_sis630 */
+ return ret;
+}
+
+static int enable_flash_sis530(struct pci_dev *dev, const char *name)
+{
+ uint8_t new, newer;
+ int ret = 0;
+ struct pci_dev *sbdev;
+
+ sbdev = find_southbridge(dev->vendor_id, name);
+ if (!sbdev)
+ return -1;
+
+ ret = enable_flash_sis_mapping(sbdev, name);
+
+ new = pci_read_byte(sbdev, 0x45);
+ new &= (~0x20);
+ new |= 0x4;
+ pci_write_byte(sbdev, 0x45, new);
+ newer = pci_read_byte(dev, 0x45);
+ if (newer != new) {
+ printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
+ printf_debug("Stuck at 0x%x\n", newer);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int enable_flash_sis540(struct pci_dev *dev, const char *name)
{
- uint8_t b;
+ uint8_t new, newer;
+ int ret = 0;
+ struct pci_dev *sbdev;
+
+ sbdev = find_southbridge(dev->vendor_id, name);
+ if (!sbdev)
+ return -1;
+
+ ret = enable_flash_sis_mapping(sbdev, name);
+
+ new = pci_read_byte(sbdev, 0x45);
+ new &= (~0x80);
+ new |= 0x40;
+ pci_write_byte(sbdev, 0x45, new);
+ newer = pci_read_byte(dev, 0x45);
+ if (newer != new) {
+ printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
+ printf_debug("Stuck at 0x%x\n", newer);
+ ret = -1;
+ }
+
+ return ret;
+}
- /* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */
- b = pci_read_byte(dev, 0x40);
- pci_write_byte(dev, 0x40, b | 0xb);
+static int enable_flash_sis630(struct pci_dev *dev, const char *name)
+{
+ uint8_t tmp;
+ uint16_t siobase;
+ int ret;
- /* Flash write enable on SiS 540/630. */
- b = pci_read_byte(dev, 0x45);
- pci_write_byte(dev, 0x45, b | 0x40);
+ ret = enable_flash_sis540(dev, name);
/* The same thing on SiS 950 Super I/O side... */
/* First probe for Super I/O on config port 0x2e. */
- OUTB(0x87, 0x2e);
- OUTB(0x01, 0x2e);
- OUTB(0x55, 0x2e);
- OUTB(0x55, 0x2e);
+ siobase = 0x2e;
+ enter_conf_mode_ite(siobase);
- if (INB(0x2f) != 0x87) {
+ if (INB(siobase + 1) != 0x87) {
/* If that failed, try config port 0x4e. */
- OUTB(0x87, 0x4e);
- OUTB(0x01, 0x4e);
- OUTB(0x55, 0x4e);
- OUTB(0xaa, 0x4e);
- if (INB(0x4f) != 0x87) {
- printf("Can not access SiS 950\n");
+ siobase = 0x4e;
+ enter_conf_mode_ite(siobase);
+ if (INB(siobase + 1) != 0x87) {
+ printf("Can not find SuperI/O.\n");
return -1;
}
- OUTB(0x24, 0x4e);
- b = INB(0x4f) | 0xfc;
- OUTB(0x24, 0x4e);
- OUTB(b, 0x4f);
- OUTB(0x02, 0x4e);
- OUTB(0x02, 0x4f);
}
- OUTB(0x24, 0x2e);
- printf_debug("2f is %#x\n", INB(0x2f));
- b = INB(0x2f) | 0xfc;
- OUTB(0x24, 0x2e);
- OUTB(b, 0x2f);
+ /* Enable flash mapping. Works for most old ITE style SuperI/O. */
+ tmp = sio_read(siobase, 0x24);
+ tmp |= 0xfc;
+ sio_write(siobase, 0x24, tmp);
- OUTB(0x02, 0x2e);
- OUTB(0x02, 0x2f);
+ exit_conf_mode_ite(siobase);
- return 0;
+ return ret;
}
/* Datasheet:
@@ -603,38 +742,6 @@ static int enable_flash_sc1100(struct pci_dev *dev, const char *name)
return 0;
}
-static int enable_flash_sis5595(struct pci_dev *dev, const char *name)
-{
- uint8_t new, newer;
-
- new = pci_read_byte(dev, 0x45);
-
- new &= (~0x20); /* Clear bit 5. */
- new |= 0x4; /* Set bit 2. */
-
- pci_write_byte(dev, 0x45, new);
-
- newer = pci_read_byte(dev, 0x45);
- if (newer != new) {
- printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
- printf_debug("Stuck at 0x%x\n", newer);
- return -1;
- }
-
- /* Extended BIOS enable = 1, Lower BIOS Enable = 1 */
- new = pci_read_byte(dev, 0x40);
- new &= 0xFB;
- new |= 0x3;
- pci_write_byte(dev, 0x40, new);
- newer = pci_read_byte(dev, 0x40);
- if (newer != new) {
- printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
- printf_debug("Stuck at 0x%x\n", newer);
- return -1;
- }
- return 0;
-}
-
/* Works for AMD-8111, VIA VT82C586A/B, VIA VT82C686A/B. */
static int enable_flash_amd8111(struct pci_dev *dev, const char *name)
{
@@ -1048,8 +1155,34 @@ const struct penable chipset_enables[] = {
{0x10de, 0x0366, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
{0x10de, 0x0367, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* Pro */
{0x10de, 0x0548, OK, "NVIDIA", "MCP67", enable_flash_mcp55},
- {0x1039, 0x0008, OK, "SiS", "SiS5595", enable_flash_sis5595},
- {0x1039, 0x0630, NT, "SiS", "SiS630", enable_flash_sis630},
+ {0x1039, 0x0496, NT, "SiS", "SiS 85C496+497", enable_flash_sis85c496},
+ {0x1039, 0x0406, NT, "SiS", "SiS 501/5101/5501", enable_flash_sis501},
+ {0x1039, 0x5511, NT, "SiS", "SiS 5511", enable_flash_sis5511},
+ {0x1039, 0x5596, NT, "SiS", "SiS 5596", enable_flash_sis5596},
+ {0x1039, 0x5571, NT, "SiS", "SiS 5571", enable_flash_sis530},
+ {0x1039, 0x5591, NT, "SiS", "SiS 5591/5592", enable_flash_sis530},
+ {0x1039, 0x5597, NT, "SiS", "SiS 5597/5598/5581/5120", enable_flash_sis530},
+ {0x1039, 0x0530, NT, "SiS", "SiS 530", enable_flash_sis530},
+ {0x1039, 0x5600, NT, "SiS", "SiS 600", enable_flash_sis530},
+ {0x1039, 0x0620, NT, "SiS", "SiS 620", enable_flash_sis530},
+ {0x1039, 0x0540, NT, "SiS", "SiS 540", enable_flash_sis540},
+ {0x1039, 0x0630, NT, "SiS", "SiS 630", enable_flash_sis630},
+ {0x1039, 0x0635, NT, "SiS", "SiS 635", enable_flash_sis630},
+ {0x1039, 0x0640, NT, "SiS", "SiS 640", enable_flash_sis630},
+ {0x1039, 0x0645, NT, "SiS", "SiS 645", enable_flash_sis630},
+ {0x1039, 0x0646, NT, "SiS", "SiS 645DX", enable_flash_sis630},
+ {0x1039, 0x0648, NT, "SiS", "SiS 648", enable_flash_sis630},
+ {0x1039, 0x0650, NT, "SiS", "SiS 650", enable_flash_sis630},
+ {0x1039, 0x0651, NT, "SiS", "SiS 651", enable_flash_sis630},
+ {0x1039, 0x0655, NT, "SiS", "SiS 655", enable_flash_sis630},
+ {0x1039, 0x0730, NT, "SiS", "SiS 730", enable_flash_sis630},
+ {0x1039, 0x0733, NT, "SiS", "SiS 733", enable_flash_sis630},
+ {0x1039, 0x0735, NT, "SiS", "SiS 735", enable_flash_sis630},
+ {0x1039, 0x0740, NT, "SiS", "SiS 740", enable_flash_sis630},
+ {0x1039, 0x0745, NT, "SiS", "SiS 745", enable_flash_sis630},
+ {0x1039, 0x0746, NT, "SiS", "SiS 746", enable_flash_sis630},
+ {0x1039, 0x0748, NT, "SiS", "SiS 748", enable_flash_sis630},
+ {0x1039, 0x0755, NT, "SiS", "SiS 755", enable_flash_sis630},
{0x1106, 0x8324, OK, "VIA", "CX700", enable_flash_vt823x},
{0x1106, 0x8231, NT, "VIA", "VT8231", enable_flash_vt823x},
{0x1106, 0x3074, NT, "VIA", "VT8233", enable_flash_vt823x},
diff --git a/flash.h b/flash.h
index 4d15816..d245824 100644
--- a/flash.h
+++ b/flash.h
@@ -389,6 +389,7 @@ int freebsd_wrmsr(int addr, msr_t msr);
/* internal.c */
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);
struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
uint16_t card_vendor, uint16_t card_device);
diff --git a/internal.c b/internal.c
index ea12bbc..fc662c5 100644
--- a/internal.c
+++ b/internal.c
@@ -42,6 +42,26 @@ struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
return NULL;
}
+struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
+{
+ struct pci_dev *temp;
+ struct pci_filter filter;
+ uint16_t tmp2;
+
+ pci_filter_init(NULL, &filter);
+ filter.vendor = vendor;
+
+ for (temp = pacc->devices; temp; temp = temp->next)
+ if (pci_filter_match(&filter, temp)) {
+ /* Read PCI class */
+ tmp2 = pci_read_word(temp, 0x0a);
+ if (tmp2 == class)
+ return temp;
+ }
+
+ return NULL;
+}
+
struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
{
struct pci_dev *temp;
OpenPOWER on IntegriCloud