summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorYinghai Lu <yinghailu@gmail.com>2005-07-08 02:49:49 +0000
committerYinghai Lu <yinghailu@gmail.com>2005-07-08 02:49:49 +0000
commit13f1c2af8be2cd7f7e99a678f5d428a65b771811 (patch)
tree27cad5581f1fa150f573149d48e82f70ba1b1d9f /src/southbridge
parent14cde9e96a777f9d75016a13b23fab0480515f58 (diff)
eric patch
1. x86_setup_mtrr take address bit. 2. generic ht, pcix, pcie beidge... 3. scan bus and reset_bus 4. ht read ctrl to decide if the ht chain is ready 5. Intel e7520 and e7525 support 6. new ich5r support 7. intel sb 6300 support. yhlu patch 1. split x86_setup_mtrrs to fixed and var 2. if (resource->flags & IORESOURCE_FIXED ) return; in device.c pick_largest_resource 3. in_conherent.c K8_SCAN_PCI_BUS git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1982 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/amd/amd8111/amd8111_reset.c60
-rw-r--r--src/southbridge/amd/amd8131-disable/Config.lb1
-rw-r--r--src/southbridge/amd/amd8131-disable/amd8131_bridge.c116
-rw-r--r--src/southbridge/amd/amd8131/amd8131_bridge.c320
-rw-r--r--src/southbridge/intel/esb6300/Config.lb12
-rw-r--r--src/southbridge/intel/esb6300/chip.h30
-rw-r--r--src/southbridge/intel/esb6300/esb6300.c48
-rw-r--r--src/southbridge/intel/esb6300/esb6300.h7
-rw-r--r--src/southbridge/intel/esb6300/esb6300_ac97.c37
-rw-r--r--src/southbridge/intel/esb6300/esb6300_bridge1c.c51
-rw-r--r--src/southbridge/intel/esb6300/esb6300_early_smbus.c107
-rw-r--r--src/southbridge/intel/esb6300/esb6300_ehci.c50
-rw-r--r--src/southbridge/intel/esb6300/esb6300_ide.c56
-rw-r--r--src/southbridge/intel/esb6300/esb6300_lpc.c410
-rw-r--r--src/southbridge/intel/esb6300/esb6300_pci.c37
-rw-r--r--src/southbridge/intel/esb6300/esb6300_pic.c109
-rw-r--r--src/southbridge/intel/esb6300/esb6300_sata.c77
-rw-r--r--src/southbridge/intel/esb6300/esb6300_smbus.c45
-rw-r--r--src/southbridge/intel/esb6300/esb6300_smbus.h105
-rw-r--r--src/southbridge/intel/esb6300/esb6300_uhci.c56
-rw-r--r--src/southbridge/intel/i82801er/i82801er_reset.c2
-rw-r--r--src/southbridge/intel/i82870/p64h2_pcibridge.c1
-rw-r--r--src/southbridge/intel/ich5r/Config.lb11
-rw-r--r--src/southbridge/intel/ich5r/chip.h30
-rw-r--r--src/southbridge/intel/ich5r/ich5r.c48
-rw-r--r--src/southbridge/intel/ich5r/ich5r.h7
-rw-r--r--src/southbridge/intel/ich5r/ich5r_ac97.c37
-rw-r--r--src/southbridge/intel/ich5r/ich5r_early_smbus.c130
-rw-r--r--src/southbridge/intel/ich5r/ich5r_ehci.c50
-rw-r--r--src/southbridge/intel/ich5r/ich5r_ide.c44
-rw-r--r--src/southbridge/intel/ich5r/ich5r_lpc.c369
-rw-r--r--src/southbridge/intel/ich5r/ich5r_pci.c37
-rw-r--r--src/southbridge/intel/ich5r/ich5r_sata.c63
-rw-r--r--src/southbridge/intel/ich5r/ich5r_smbus.c45
-rw-r--r--src/southbridge/intel/ich5r/ich5r_smbus.h105
-rw-r--r--src/southbridge/intel/ich5r/ich5r_uhci.c56
-rw-r--r--src/southbridge/intel/ich5r/ich5r_watchdog.c28
-rw-r--r--src/southbridge/intel/pxhd/Config.lb2
-rw-r--r--src/southbridge/intel/pxhd/chip.h5
-rw-r--r--src/southbridge/intel/pxhd/pxhd.h6
-rw-r--r--src/southbridge/intel/pxhd/pxhd_bridge.c258
41 files changed, 3054 insertions, 14 deletions
diff --git a/src/southbridge/amd/amd8111/amd8111_reset.c b/src/southbridge/amd/amd8111/amd8111_reset.c
index 822a1e378f..435904aabd 100644
--- a/src/southbridge/amd/amd8111/amd8111_reset.c
+++ b/src/southbridge/amd/amd8111/amd8111_reset.c
@@ -1,14 +1,15 @@
+/* Include this file in the mainboards reset.c
+ */
#include <arch/io.h>
+#include <device/pci_ids.h>
#define PCI_DEV(BUS, DEV, FN) ( \
(((BUS) & 0xFF) << 16) | \
(((DEV) & 0x1f) << 11) | \
(((FN) & 0x7) << 8))
-#define AMD8111_RESET PCI_DEV( \
- HARD_RESET_BUS, \
- HARD_RESET_DEVICE, \
- HARD_RESET_FUNCTION)
+#define PCI_ID(VENDOR_ID, DEVICE_ID) \
+ ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))
typedef unsigned device_t;
@@ -36,10 +37,57 @@ static unsigned pci_read_config32(device_t dev, unsigned where)
return inl(0xCFC);
}
+#define PCI_DEV_INVALID (0xffffffffU)
+static device_t pci_locate_device(unsigned pci_id, unsigned bus)
+{
+ device_t dev, last;
+ dev = PCI_DEV(bus, 0, 0);
+ last = PCI_DEV(bus, 31, 7);
+ for(; dev <= last; dev += PCI_DEV(0,0,1)) {
+ unsigned int id;
+ id = pci_read_config32(dev, 0);
+ if (id == pci_id) {
+ return dev;
+ }
+ }
+ return PCI_DEV_INVALID;
+}
+
#include "../../../northbridge/amd/amdk8/reset_test.c"
-void hard_reset(void)
+static unsigned node_link_to_bus(unsigned node, unsigned link)
{
+ unsigned reg;
+
+ for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
+ unsigned config_map;
+ config_map = pci_read_config32(PCI_DEV(0, 0x18, 1), reg);
+ if ((config_map & 3) != 3) {
+ continue;
+ }
+ if ((((config_map >> 4) & 7) == node) &&
+ (((config_map >> 8) & 3) == link))
+ {
+ return (config_map >> 16) & 0xff;
+ }
+ }
+ return 0;
+}
+
+static void amd8111_hard_reset(unsigned node, unsigned link)
+{
+ device_t dev;
+ unsigned bus;
+
+ /* Find the device.
+ * There can only be one 8111 on a hypertransport chain/bus.
+ */
+ bus = node_link_to_bus(node, link);
+ dev = pci_locate_device(
+ PCI_ID(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_ISA),
+ bus);
+
+ /* Reset */
set_bios_reset();
- pci_write_config8(AMD8111_RESET, 0x47, 1);
+ pci_write_config8(dev, 0x47, 1);
}
diff --git a/src/southbridge/amd/amd8131-disable/Config.lb b/src/southbridge/amd/amd8131-disable/Config.lb
new file mode 100644
index 0000000000..9968e9ad1d
--- /dev/null
+++ b/src/southbridge/amd/amd8131-disable/Config.lb
@@ -0,0 +1 @@
+driver amd8131_bridge.o
diff --git a/src/southbridge/amd/amd8131-disable/amd8131_bridge.c b/src/southbridge/amd/amd8131-disable/amd8131_bridge.c
new file mode 100644
index 0000000000..648dbba250
--- /dev/null
+++ b/src/southbridge/amd/amd8131-disable/amd8131_bridge.c
@@ -0,0 +1,116 @@
+/*
+ * (C) 2004 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+
+static void amd8131_bus_read_resources(device_t dev)
+{
+ return;
+}
+
+static void amd8131_bus_set_resources(device_t dev)
+{
+#if 0
+ pci_bus_read_resources(dev);
+#endif
+ return;
+}
+
+static void amd8131_bus_enable_resources(device_t dev)
+{
+#if 0
+ pci_dev_set_resources(dev);
+#endif
+ return;
+}
+
+static void amd8131_bus_init(device_t dev)
+{
+#if 0
+ pcix_init(dev);
+#endif
+ return;
+}
+
+static unsigned int amd8131_scan_bus(device_t bus, unsigned int max)
+{
+#if 0
+ max = pcix_scan_bridge(bus, max);
+#endif
+ return max;
+}
+
+static void amd8131_enable(device_t dev)
+{
+ uint32_t buses;
+ uint16_t cr;
+
+ /* Clear all status bits and turn off memory, I/O and master enables. */
+ pci_write_config16(dev, PCI_COMMAND, 0x0000);
+ pci_write_config16(dev, PCI_STATUS, 0xffff);
+
+ /*
+ * Read the existing primary/secondary/subordinate bus
+ * number configuration.
+ */
+ buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
+
+ /* Configure the bus numbers for this bridge: the configuration
+ * transactions will not be propagated by the bridge if it is not
+ * correctly configured.
+ */
+ buses &= 0xff000000;
+ buses |= (((unsigned int) (dev->bus->secondary) << 0) |
+ ((unsigned int) (dev->bus->secondary) << 8) |
+ ((unsigned int) (dev->bus->secondary) << 16));
+ pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
+}
+
+static struct device_operations pcix_ops = {
+ .read_resources = amd8131_bus_read_resources,
+ .set_resources = amd8131_bus_set_resources,
+ .enable_resources = amd8131_bus_enable_resources,
+ .init = amd8131_bus_init,
+ .scan_bus = 0,
+ .enable = amd8131_enable,
+};
+
+static struct pci_driver pcix_driver __pci_driver = {
+ .ops = &pcix_ops,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = 0x7450,
+};
+
+
+static void ioapic_enable(device_t dev)
+{
+ uint32_t value;
+ value = pci_read_config32(dev, 0x44);
+ if (dev->enabled) {
+ value |= ((1 << 1) | (1 << 0));
+ } else {
+ value &= ~((1 << 1) | (1 << 0));
+ }
+ pci_write_config32(dev, 0x44, value);
+}
+
+static struct device_operations ioapic_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = 0,
+ .enable = ioapic_enable,
+};
+
+static struct pci_driver ioapic_driver __pci_driver = {
+ .ops = &ioapic_ops,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = 0x7451,
+
+};
diff --git a/src/southbridge/amd/amd8131/amd8131_bridge.c b/src/southbridge/amd/amd8131/amd8131_bridge.c
index 357059d347..828b083f2e 100644
--- a/src/southbridge/amd/amd8131/amd8131_bridge.c
+++ b/src/southbridge/amd/amd8131/amd8131_bridge.c
@@ -7,10 +7,273 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <pc80/mc146818rtc.h>
+#include <device/pci_def.h>
+#include <device/pcix.h>
#define NMI_OFF 0
-static void pcix_init(device_t dev)
+#define NPUML 0xD9 /* Non prefetchable upper memory limit */
+#define NPUMB 0xD8 /* Non prefetchable upper memory base */
+
+static void amd8131_walk_children(struct bus *bus,
+ void (*visit)(device_t dev, void *ptr), void *ptr)
+{
+ device_t child;
+ for(child = bus->children; child; child = child->sibling)
+ {
+ if (child->path.type != DEVICE_PATH_PCI) {
+ continue;
+ }
+ if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ amd8131_walk_children(&child->link[0], visit, ptr);
+ }
+ visit(child, ptr);
+ }
+}
+
+struct amd8131_bus_info {
+ unsigned sstatus;
+ unsigned rev;
+ int errata_56;
+ int master_devices;
+ int max_func;
+};
+
+static void amd8131_count_dev(device_t dev, void *ptr)
+{
+ struct amd8131_bus_info *info = ptr;
+ /* Don't count pci bridges */
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ info->master_devices++;
+ }
+ if (PCI_FUNC(dev->path.u.pci.devfn) > info->max_func) {
+ info->max_func = PCI_FUNC(dev->path.u.pci.devfn);
+ }
+}
+
+
+static void amd8131_pcix_tune_dev(device_t dev, void *ptr)
+{
+ struct amd8131_bus_info *info = ptr;
+ unsigned cap;
+ unsigned status, cmd, orig_cmd;
+ unsigned max_read, max_tran;
+ int sib_funcs, sibs;
+ device_t sib;
+
+ if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) {
+ return;
+ }
+ cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (!cap) {
+ return;
+ }
+ /* How many siblings does this device have? */
+ sibs = info->master_devices - 1;
+ /* Count how many sibling functions this device has */
+ sib_funcs = 0;
+ for(sib = dev->bus->children; sib; sib = sib->sibling) {
+ if (sib == dev) {
+ continue;
+ }
+ if (PCI_SLOT(sib->path.u.pci.devfn) != PCI_SLOT(dev->path.u.pci.devfn)) {
+ continue;
+ }
+ sib_funcs++;
+ }
+
+
+ printk_debug("%s AMD8131 PCI-X tuning\n", dev_path(dev));
+ status = pci_read_config32(dev, cap + PCI_X_STATUS);
+ orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD);
+
+ max_read = (status & PCI_X_STATUS_MAX_READ) >> 21;
+ max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23;
+
+ /* Errata #49 don't allow 4K transactions */
+ if (max_read >= 2) {
+ max_read = 2;
+ }
+
+ /* Errata #37 Limit the number of split transactions to avoid starvation */
+ if (sibs >= 2) {
+ /* At most 2 outstanding split transactions when we have
+ * 3 or more bus master devices on the bus.
+ */
+ if (max_tran > 1) {
+ max_tran = 1;
+ }
+ }
+ else if (sibs == 1) {
+ /* At most 4 outstanding split transactions when we have
+ * 2 bus master devices on the bus.
+ */
+ if (max_tran > 3) {
+ max_tran = 3;
+ }
+ }
+ else {
+ /* At most 8 outstanding split transactions when we have
+ * only one bus master device on the bus.
+ */
+ if (max_tran > 4) {
+ max_tran = 4;
+ }
+ }
+ /* Errata #56 additional limits when the bus runs at 133Mhz */
+ if (info->errata_56 &&
+ (PCI_X_SSTATUS_MFREQ(info->sstatus) == PCI_X_SSTATUS_MODE1_133MHZ))
+ {
+ unsigned limit_read;
+ /* Look at the number of siblings and compute the
+ * largest legal read size.
+ */
+ if (sib_funcs == 0) {
+ /* 2k reads */
+ limit_read = 2;
+ }
+ else if (sib_funcs <= 1) {
+ /* 1k reads */
+ limit_read = 1;
+ }
+ else {
+ /* 512 byte reads */
+ limit_read = 0;
+ }
+ if (max_read > limit_read) {
+ max_read = limit_read;
+ }
+ /* Look at the read size and the nubmer of siblings
+ * and compute how many outstanding transactions I can have.
+ */
+ if (max_read == 2) {
+ /* 2K reads */
+ if (max_tran > 0) {
+ /* Only 1 outstanding transaction allowed */
+ max_tran = 0;
+ }
+ }
+ else if (max_read == 1) {
+ /* 1K reads */
+ if (max_tran > (1 - sib_funcs)) {
+ /* At most 2 outstanding transactions */
+ max_tran = 1 - sib_funcs;
+ }
+ }
+ else {
+ /* 512 byte reads */
+ max_read = 0;
+ if (max_tran > (2 - sib_funcs)) {
+ /* At most 3 outstanding transactions */
+ max_tran = 2 - sib_funcs;
+ }
+ }
+ }
+#if 0
+ printk_debug("%s max_read: %d max_tran: %d sibs: %d sib_funcs: %d\n",
+ dev_path(dev), max_read, max_tran, sibs, sib_funcs, sib_funcs);
+#endif
+ if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) {
+ cmd &= ~PCI_X_CMD_MAX_READ;
+ cmd |= max_read << 2;
+ }
+ if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) {
+ cmd &= ~PCI_X_CMD_MAX_SPLIT;
+ cmd |= max_tran << 4;
+ }
+
+ /* Don't attempt to handle PCI-X errors */
+ cmd &= ~PCI_X_CMD_DPERR_E;
+ /* The 8131 does not work properly with relax ordering enabled.
+ * Errata #58
+ */
+ cmd &= ~PCI_X_CMD_ERO;
+ if (orig_cmd != cmd) {
+ pci_write_config16(dev, cap + PCI_X_CMD, cmd);
+ }
+}
+static unsigned int amd8131_scan_bus(struct bus *bus,
+ unsigned min_devfn, unsigned max_devfn, unsigned int max)
+{
+ struct amd8131_bus_info info;
+ struct bus *pbus;
+ unsigned pos;
+
+
+ /* Find the children on the bus */
+ max = pci_scan_bus(bus, min_devfn, max_devfn, max);
+
+ /* Find the revision of the 8131 */
+ info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION);
+
+ /* See which errata apply */
+ info.errata_56 = info.rev <= 0x12;
+
+ /* Find the pcix capability and get the secondary bus status */
+ pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX);
+ info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS);
+
+ /* Print the PCI-X bus speed */
+ printk_debug("PCI: %02x: %s\n", bus->secondary, pcix_speed(info.sstatus));
+
+
+ /* Examine the bus and find out how loaded it is */
+ info.max_func = 0;
+ info.master_devices = 0;
+ amd8131_walk_children(bus, amd8131_count_dev, &info);
+
+ /* Disable the bus if there are no devices on it or
+ * we are running at 133Mhz and have a 4 function device.
+ * see errata #56
+ */
+ if (!bus->children ||
+ (info.errata_56 &&
+ (info.max_func >= 3) &&
+ (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_MODE1_133MHZ)))
+ {
+ unsigned pcix_misc;
+ /* Disable all of my children */
+ disable_children(bus);
+
+ /* Remember the device is disabled */
+ bus->dev->enabled = 0;
+
+ /* Disable the PCI-X clocks */
+ pcix_misc = pci_read_config32(bus->dev, 0x40);
+ pcix_misc &= ~(0x1f << 16);
+ pci_write_config32(bus->dev, 0x40, pcix_misc);
+
+ return max;
+ }
+
+ /* If we are in conventional PCI mode nothing more is necessary.
+ */
+ if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) {
+ return max;
+ }
+
+
+ /* Tune the devices on the bus */
+ amd8131_walk_children(bus, amd8131_pcix_tune_dev, &info);
+
+ /* Don't allow the 8131 or any of it's parent busses to
+ * implement relaxed ordering. Errata #58
+ */
+ for(pbus = bus; !pbus->disable_relaxed_ordering; pbus = pbus->dev->bus) {
+ printk_spew("%s disabling relaxed ordering\n",
+ bus_path(pbus));
+ pbus->disable_relaxed_ordering = 1;
+ }
+ return max;
+}
+
+static unsigned int amd8131_scan_bridge(device_t dev, unsigned int max)
+{
+ return do_pci_scan_bridge(dev, max, amd8131_scan_bus);
+}
+
+
+static void amd8131_pcix_init(device_t dev)
{
uint32_t dword;
uint16_t word;
@@ -24,18 +287,19 @@ static void pcix_init(device_t dev)
/* Set drive strength */
word = pci_read_config16(dev, 0xe0);
- word = 0x0808;
+ word = 0x0404;
pci_write_config16(dev, 0xe0, word);
word = pci_read_config16(dev, 0xe4);
- word = 0x0808;
+ word = 0x0404;
pci_write_config16(dev, 0xe4, word);
/* Set impedance */
word = pci_read_config16(dev, 0xe8);
- word = 0x0f0f;
+ word = 0x0404;
pci_write_config16(dev, 0xe8, word);
/* Set discard unrequested prefetch data */
+ /* Errata #51 */
word = pci_read_config16(dev, 0x4c);
word |= 1;
pci_write_config16(dev, 0x4c, word);
@@ -76,16 +340,58 @@ static void pcix_init(device_t dev)
dword |= (1<<1);
pci_write_config32(dev, 0xc8, dword);
}
-
return;
}
+#define BRIDGE_40_BIT_SUPPORT 0
+#if BRIDGE_40_BIT_SUPPORT
+static void bridge_read_resources(struct device *dev)
+{
+ struct resource *res;
+ pci_bus_read_resources(dev);
+ res = find_resource(dev, PCI_MEMORY_BASE);
+ if (res) {
+ res->limit = 0xffffffffffULL;
+ }
+}
+
+static void bridge_set_resources(struct device *dev)
+{
+ struct resource *res;
+ res = find_resource(dev, PCI_MEMORY_BASE);
+ if (res) {
+ resource_t base, end;
+ /* set the memory range */
+ dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ res->flags |= IORESOURCE_STORED;
+ compute_allocate_resource(&dev->link[0], res,
+ IORESOURCE_MEM | IORESOURCE_PREFETCH,
+ IORESOURCE_MEM);
+ base = res->base;
+ end = resource_end(res);
+ pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
+ pci_write_config8(dev, NPUML, (base >> 32) & 0xff);
+ pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
+ pci_write_config8(dev, NPUMB, (end >> 32) & 0xff);
+
+ report_resource_stored(dev, res, "");
+ }
+ pci_dev_set_resources(dev);
+}
+#endif /* BRIDGE_40_BIT_SUPPORT */
+
static struct device_operations pcix_ops = {
+#if BRIDGE_40_BIT_SUPPORT
+ .read_resources = bridge_read_resources,
+ .set_resources = bridge_set_resources,
+#else
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
+#endif
.enable_resources = pci_bus_enable_resources,
- .init = pcix_init,
- .scan_bus = pci_scan_bridge,
+ .init = amd8131_pcix_init,
+ .scan_bus = amd8131_scan_bridge,
+ .reset_bus = pci_bus_reset,
};
static struct pci_driver pcix_driver __pci_driver = {
diff --git a/src/southbridge/intel/esb6300/Config.lb b/src/southbridge/intel/esb6300/Config.lb
new file mode 100644
index 0000000000..9674c1f818
--- /dev/null
+++ b/src/southbridge/intel/esb6300/Config.lb
@@ -0,0 +1,12 @@
+config chip.h
+driver esb6300.o
+driver esb6300_uhci.o
+driver esb6300_lpc.o
+driver esb6300_ide.o
+driver esb6300_sata.o
+driver esb6300_ehci.o
+driver esb6300_smbus.o
+driver esb6300_pci.o
+driver esb6300_pic.o
+driver esb6300_bridge1c.o
+driver esb6300_ac97.o
diff --git a/src/southbridge/intel/esb6300/chip.h b/src/southbridge/intel/esb6300/chip.h
new file mode 100644
index 0000000000..ff74e615fd
--- /dev/null
+++ b/src/southbridge/intel/esb6300/chip.h
@@ -0,0 +1,30 @@
+struct southbridge_intel_esb6300_config
+{
+#define ESB6300_GPIO_USE_MASK 0x03
+#define ESB6300_GPIO_USE_DEFAULT 0x00
+#define ESB6300_GPIO_USE_AS_NATIVE 0x01
+#define ESB6300_GPIO_USE_AS_GPIO 0x02
+
+#define ESB6300_GPIO_SEL_MASK 0x0c
+#define ESB6300_GPIO_SEL_DEFAULT 0x00
+#define ESB6300_GPIO_SEL_OUTPUT 0x04
+#define ESB6300_GPIO_SEL_INPUT 0x08
+
+#define ESB6300_GPIO_LVL_MASK 0x30
+#define ESB6300_GPIO_LVL_DEFAULT 0x00
+#define ESB6300_GPIO_LVL_LOW 0x10
+#define ESB6300_GPIO_LVL_HIGH 0x20
+#define ESB6300_GPIO_LVL_BLINK 0x30
+
+#define ESB6300_GPIO_INV_MASK 0xc0
+#define ESB6300_GPIO_INV_DEFAULT 0x00
+#define ESB6300_GPIO_INV_OFF 0x40
+#define ESB6300_GPIO_INV_ON 0x80
+
+ /* GPIO use select */
+ unsigned char gpio[64];
+ unsigned int pirq_a_d;
+ unsigned int pirq_e_h;
+};
+extern struct chip_operations southbridge_intel_esb6300_ops;
+
diff --git a/src/southbridge/intel/esb6300/esb6300.c b/src/southbridge/intel/esb6300/esb6300.c
new file mode 100644
index 0000000000..3551a59ea6
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300.c
@@ -0,0 +1,48 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "esb6300.h"
+
+void esb6300_enable(device_t dev)
+{
+ device_t lpc_dev;
+ unsigned index = 0;
+ uint16_t reg_old, reg;
+
+ /* See if we are on the behind the 6300 pci bridge */
+ lpc_dev = dev_find_slot(dev->bus->secondary, PCI_DEVFN(0x1f, 0));
+ if((dev->path.u.pci.devfn &0xf8)== 0xf8) {
+ index = dev->path.u.pci.devfn & 7;
+ }
+ else if((dev->path.u.pci.devfn &0xf8)== 0xe8) {
+ index = (dev->path.u.pci.devfn & 7) +8;
+ }
+ if ((!lpc_dev) || (index >= 16) || ((1<<index)&0x3091)) {
+ return;
+ }
+ if ((lpc_dev->vendor != PCI_VENDOR_ID_INTEL) ||
+ (lpc_dev->device != PCI_DEVICE_ID_INTEL_6300ESB_ISA)) {
+ uint32_t id;
+ id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
+ if (id != (PCI_VENDOR_ID_INTEL |
+ (PCI_DEVICE_ID_INTEL_6300ESB_ISA << 16))) {
+ return;
+ }
+ }
+
+ reg = reg_old = pci_read_config16(lpc_dev, 0xf2);
+ reg &= ~(1 << index);
+ if (!dev->enabled) {
+ reg |= (1 << index);
+ }
+ if (reg != reg_old) {
+ pci_write_config16(lpc_dev, 0xf2, reg);
+ }
+
+}
+
+struct chip_operations southbridge_intel_esb6300_ops = {
+ CHIP_NAME("INTEL 6300ESB")
+ .enable_dev = esb6300_enable,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300.h b/src/southbridge/intel/esb6300/esb6300.h
new file mode 100644
index 0000000000..2c91fcba98
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300.h
@@ -0,0 +1,7 @@
+#ifndef ESB6300_H
+#define ESB6300_H
+#include "chip.h"
+
+void esb6300_enable(device_t dev);
+
+#endif /* ESB6300 */
diff --git a/src/southbridge/intel/esb6300/esb6300_ac97.c b/src/southbridge/intel/esb6300/esb6300_ac97.c
new file mode 100644
index 0000000000..cc221f6e64
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_ac97.c
@@ -0,0 +1,37 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void ac97_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* Write the subsystem vendor and device id */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = ac97_set_subsystem,
+};
+static struct device_operations ac97_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ac97_audio_driver __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_AC97_AUDIO,
+};
+static struct pci_driver ac97_modem_driver __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_AC97_MODEM,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300_bridge1c.c b/src/southbridge/intel/esb6300/esb6300_bridge1c.c
new file mode 100644
index 0000000000..49e3b056a0
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_bridge1c.c
@@ -0,0 +1,51 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void bridge1c_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* configuration */
+ pci_write_config8(dev, 0x1b, 0x30);
+// pci_write_config8(dev, 0x3e, 0x07);
+ pci_write_config8(dev, 0x3e, 0x04); /* parity ignore */
+ pci_write_config8(dev, 0x6c, 0x0c); /* undocumented */
+ pci_write_config8(dev, 0xe0, 0x20);
+
+ /* SRB enable */
+ pci_write_config16(dev, 0xe4, 0x0232);
+
+ /* Burst size */
+ pci_write_config8(dev, 0xf0, 0x02);
+
+ /* prefetch threshold size */
+ pci_write_config16(dev, 0xf8, 0x2121);
+
+ /* primary latency */
+ pci_write_config8(dev, 0x0d, 0x28);
+
+ /* multi transaction timer */
+ pci_write_config8(dev, 0x42, 0x08);
+
+}
+
+static struct device_operations pci_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = bridge1c_init,
+ .scan_bus = pci_scan_bridge,
+ .ops_pci = 0,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_BRIDGE1C,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_early_smbus.c b/src/southbridge/intel/esb6300/esb6300_early_smbus.c
new file mode 100644
index 0000000000..e115e3a2fa
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_early_smbus.c
@@ -0,0 +1,107 @@
+#include "esb6300_smbus.h"
+
+#define SMBUS_IO_BASE 0x0f00
+
+static void enable_smbus(void)
+{
+ device_t dev;
+ dev = pci_locate_device(PCI_ID(0x8086, 0x25a4), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("SMBUS controller not found\r\n");
+ }
+ uint8_t enable;
+ print_spew("SMBus controller enabled\r\n");
+ pci_write_config32(dev, 0x20, SMBUS_IO_BASE | 1);
+ pci_write_config8(dev, 0x40, 1);
+ pci_write_config8(dev, 0x4, 1);
+ /* SMBALERT_DIS */
+ pci_write_config8(dev, 0x11, 4);
+
+ /* Disable interrupt generation */
+ outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+ dev = pci_locate_device(PCI_ID(0x8086, 0x25a1), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("ISA bridge not found\r\n");
+ }
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+ return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
+}
+
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+ if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) {
+ return;
+ }
+ return;
+}
+
+static int smbus_write_block(unsigned device, unsigned length, unsigned cmd,
+ unsigned data1, unsigned data2)
+{
+ unsigned char global_control_register;
+ unsigned char global_status_register;
+ unsigned char byte;
+ unsigned char stat;
+ int i;
+
+ /* chear the PM timeout flags, SECOND_TO_STS */
+ outw(inw(0x0400 + 0x66), 0x0400 + 0x66);
+
+ if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) {
+ return -2;
+ }
+
+ /* setup transaction */
+ /* Obtain ownership */
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+ for(stat=0;(stat&0x40)==0;) {
+ stat = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+ /* clear the done bit */
+ outb(0x80, SMBUS_IO_BASE + SMBHSTSTAT);
+ /* disable interrupts */
+ outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1), SMBUS_IO_BASE + SMBXMITADD);
+
+ /* set the command address */
+ outb(cmd & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+
+ /* set the block length */
+ outb(length & 0xFF, SMBUS_IO_BASE + SMBHSTDAT0);
+
+ /* try sending out the first byte of data here */
+ byte=(data1>>(0))&0x0ff;
+ outb(byte,SMBUS_IO_BASE + SMBBLKDAT);
+ /* issue a block write command */
+ outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x5 << 2) | 0x40,
+ SMBUS_IO_BASE + SMBHSTCTL);
+
+ for(i=0;i<length;i++) {
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_blk_done(SMBUS_IO_BASE) < 0) {
+ return -3;
+ }
+
+ /* load the next byte */
+ if(i>3)
+ byte=(data2>>(i%4))&0x0ff;
+ else
+ byte=(data1>>(i))&0x0ff;
+ outb(byte,SMBUS_IO_BASE + SMBBLKDAT);
+
+ /* clear the done bit */
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
+ SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+
+ print_debug("SMBUS Block complete\r\n");
+ return 0;
+}
+
diff --git a/src/southbridge/intel/esb6300/esb6300_ehci.c b/src/southbridge/intel/esb6300/esb6300_ehci.c
new file mode 100644
index 0000000000..58dcd9593c
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_ehci.c
@@ -0,0 +1,50 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void ehci_init(struct device *dev)
+{
+ uint32_t cmd;
+
+ printk_debug("EHCI: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+
+ printk_debug("done.\n");
+}
+
+static void ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ uint8_t access_cntl;
+ access_cntl = pci_read_config8(dev, 0x80);
+ /* Enable writes to protected registers */
+ pci_write_config8(dev, 0x80, access_cntl | 1);
+ /* Write the subsystem vendor and device id */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+ /* Restore protection */
+ pci_write_config8(dev, 0x80, access_cntl);
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = &ehci_set_subsystem,
+};
+static struct device_operations ehci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ehci_init,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ehci_driver __pci_driver = {
+ .ops = &ehci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_EHCI,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300_ide.c b/src/southbridge/intel/esb6300/esb6300_ide.c
new file mode 100644
index 0000000000..bb77ad7726
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_ide.c
@@ -0,0 +1,56 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void ide_init(struct device *dev)
+{
+
+ /* Enable ide devices so the linux ide driver will work */
+ uint16_t word;
+
+ /* Enable IDE devices */
+ pci_write_config16(dev, 0x40, 0x0a307);
+ pci_write_config16(dev, 0x42, 0x0a307);
+ pci_write_config8(dev, 0x48, 0x05);
+ pci_write_config16(dev, 0x4a, 0x0101);
+ pci_write_config16(dev, 0x54, 0x5055);
+
+#if 0
+ word = pci_read_config16(dev, 0x40);
+ word |= (1 << 15);
+ pci_write_config16(dev, 0x40, word);
+ word = pci_read_config16(dev, 0x42);
+ word |= (1 << 15);
+ pci_write_config16(dev, 0x42, word);
+#endif
+ printk_debug("IDE Enabled\n");
+}
+
+static void esb6300_ide_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* This value is also visible in uchi[0-2] and smbus functions */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = esb6300_ide_set_subsystem,
+};
+static struct device_operations ide_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ide_init,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ide_driver __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_IDE,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_lpc.c b/src/southbridge/intel/esb6300/esb6300_lpc.c
new file mode 100644
index 0000000000..caef888d2a
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_lpc.c
@@ -0,0 +1,410 @@
+/*
+ * (C) 2004 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <arch/io.h>
+#include "esb6300.h"
+
+#define ACPI_BAR 0x40
+#define GPIO_BAR 0x58
+
+#define NMI_OFF 0
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON 1
+
+#ifndef MAINBOARD_POWER_ON_AFTER_FAIL
+#define MAINBOARD_POWER_ON_AFTER_FAIL MAINBOARD_POWER_ON
+#endif
+
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+
+static void setup_ioapic(device_t dev)
+{
+ int i;
+ unsigned long value_low, value_high;
+ unsigned long ioapic_base = 0xfec00000;
+ volatile unsigned long *l;
+ unsigned interrupts;
+
+ l = (unsigned long *) ioapic_base;
+
+ l[0] = 0x01;
+ interrupts = (l[04] >> 16) & 0xff;
+ for (i = 0; i < interrupts; i++) {
+ l[0] = (i * 2) + 0x10;
+ l[4] = DISABLED;
+ value_low = l[4];
+ l[0] = (i * 2) + 0x11;
+ l[4] = NONE; /* Should this be an address? */
+ value_high = l[4];
+ if (value_low == 0xffffffff) {
+ printk_warning("%d IO APIC not responding.\n",
+ dev_path(dev));
+ return;
+ }
+ }
+
+ /* Put the ioapic in virtual wire mode */
+ l[0] = 0 + 0x10;
+ l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
+}
+
+#define SERIRQ_CNTL 0x64
+static void esb6300_enable_serial_irqs(device_t dev)
+{
+ /* set packet length and toggle silent mode bit */
+ pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
+ pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
+}
+
+#define PCI_DMA_CFG 0x90
+static void esb6300_pci_dma_cfg(device_t dev)
+{
+ /* Set PCI DMA CFG to lpc I/F DMA */
+ pci_write_config16(dev, PCI_DMA_CFG, 0xfcff);
+}
+
+#define LPC_EN 0xe6
+static void esb6300_enable_lpc(device_t dev)
+{
+ /* lpc i/f enable */
+ pci_write_config8(dev, LPC_EN, 0x0d);
+}
+
+typedef struct southbridge_intel_esb6300_config config_t;
+
+static void set_esb6300_gpio_use_sel(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_use_sel, gpio_use_sel2;
+ int i;
+
+// gpio_use_sel = 0x1B003100;
+// gpio_use_sel2 = 0x03000000;
+ gpio_use_sel = 0x1BBC31C0;
+ gpio_use_sel2 = 0x03000FE1;
+#if 0
+ for(i = 0; i < 64; i++) {
+ int val;
+ switch(config->gpio[i] & ESB6300_GPIO_USE_MASK) {
+ case ESB6300_GPIO_USE_AS_NATIVE: val = 0; break;
+ case ESB6300_GPIO_USE_AS_GPIO: val = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_use_sel &= ~( 1 << i);
+ gpio_use_sel |= (val << i);
+ } else {
+ gpio_use_sel2 &= ~( 1 << (i - 32));
+ gpio_use_sel2 |= (val << (i - 32));
+ }
+ }
+#endif
+ outl(gpio_use_sel, res->base + 0x00);
+ outl(gpio_use_sel2, res->base + 0x30);
+}
+
+static void set_esb6300_gpio_direction(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_io_sel, gpio_io_sel2;
+ int i;
+
+// gpio_io_sel = 0x0000ffff;
+// gpio_io_sel2 = 0x00000000;
+ gpio_io_sel = 0x1900ffff;
+ gpio_io_sel2 = 0x00000fe1;
+#if 0
+ for(i = 0; i < 64; i++) {
+ int val;
+ switch(config->gpio[i] & ESB6300_GPIO_SEL_MASK) {
+ case ESB6300_GPIO_SEL_OUTPUT: val = 0; break;
+ case ESB6300_GPIO_SEL_INPUT: val = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_io_sel &= ~( 1 << i);
+ gpio_io_sel |= (val << i);
+ } else {
+ gpio_io_sel2 &= ~( 1 << (i - 32));
+ gpio_io_sel2 |= (val << (i - 32));
+ }
+ }
+#endif
+ outl(gpio_io_sel, res->base + 0x04);
+ outl(gpio_io_sel2, res->base + 0x34);
+}
+
+static void set_esb6300_gpio_level(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_lvl, gpio_lvl2;
+ uint32_t gpio_blink;
+ int i;
+
+// gpio_lvl = 0x1b3f0000;
+// gpio_blink = 0x00040000;
+// gpio_lvl2 = 0x00000fff;
+ gpio_lvl = 0x19370000;
+ gpio_blink = 0x00000000;
+ gpio_lvl2 = 0x00000fff;
+#if 0
+ for(i = 0; i < 64; i++) {
+ int val, blink;
+ switch(config->gpio[i] & ESB6300_GPIO_LVL_MASK) {
+ case ESB6300_GPIO_LVL_LOW: val = 0; blink = 0; break;
+ case ESB6300_GPIO_LVL_HIGH: val = 1; blink = 0; break;
+ case ESB6300_GPIO_LVL_BLINK: val = 1; blink = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_lvl &= ~( 1 << i);
+ gpio_blink &= ~( 1 << i);
+ gpio_lvl |= ( val << i);
+ gpio_blink |= (blink << i);
+ } else {
+ gpio_lvl2 &= ~( 1 << (i - 32));
+ gpio_lvl2 |= (val << (i - 32));
+ }
+ }
+#endif
+ outl(gpio_lvl, res->base + 0x0c);
+ outl(gpio_blink, res->base + 0x18);
+ outl(gpio_lvl2, res->base + 0x38);
+}
+
+static void set_esb6300_gpio_inv(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_inv;
+ int i;
+
+ gpio_inv = 0x00003100;
+#if 0
+ for(i = 0; i < 32; i++) {
+ int val;
+ switch(config->gpio[i] & ESB6300_GPIO_INV_MASK) {
+ case ESB6300_GPIO_INV_OFF: val = 0; break;
+ case ESB6300_GPIO_INV_ON: val = 1; break;
+ default:
+ continue;
+ }
+ gpio_inv &= ~( 1 << i);
+ gpio_inv |= (val << i);
+ }
+#endif
+ outl(gpio_inv, res->base + 0x2c);
+}
+
+static void esb6300_pirq_init(device_t dev)
+{
+ config_t *config;
+
+ /* Get the chip configuration */
+ config = dev->chip_info;
+
+ if(config->pirq_a_d) {
+ pci_write_config32(dev, 0x60, config->pirq_a_d);
+ }
+ if(config->pirq_e_h) {
+ pci_write_config32(dev, 0x68, config->pirq_e_h);
+ }
+}
+
+
+static void esb6300_gpio_init(device_t dev)
+{
+ struct resource *res;
+ config_t *config;
+
+ /* Skip if I don't have any configuration */
+ if (!dev->chip_info) {
+ return;
+ }
+ /* The programmer is responsible for ensuring
+ * a valid gpio configuration.
+ */
+
+ /* Get the chip configuration */
+ config = dev->chip_info;
+ /* Find the GPIO bar */
+ res = find_resource(dev, GPIO_BAR);
+ if (!res) {
+ return;
+ }
+
+ /* Set the use selects */
+ set_esb6300_gpio_use_sel(dev, res, config);
+
+ /* Set the IO direction */
+ set_esb6300_gpio_direction(dev, res, config);
+
+ /* Setup the input inverters */
+ set_esb6300_gpio_inv(dev, res, config);
+
+ /* Set the value on the GPIO output pins */
+ set_esb6300_gpio_level(dev, res, config);
+
+}
+
+
+static void lpc_init(struct device *dev)
+{
+ uint8_t byte;
+ uint32_t value;
+ int pwr_on=MAINBOARD_POWER_ON_AFTER_FAIL;
+
+ /* sata settings */
+ pci_write_config32(dev, 0x58, 0x00001181);
+
+ /* IO APIC initialization */
+ value = pci_read_config32(dev, 0xd0);
+ value |= (1 << 8)|(1<<7);
+ value |= (6 << 0)|(1<<13)|(1<<11);
+ pci_write_config32(dev, 0xd0, value);
+ setup_ioapic(dev);
+
+ /* disable reset timer */
+ pci_write_config8(dev, 0xd4, 0x02);
+
+ /* cmos ram 2nd 128 */
+ pci_write_config8(dev, 0xd8, 0x04);
+
+ /* comm 2 */
+ pci_write_config8(dev, 0xe0, 0x10);
+
+ /* fwh sellect */
+ pci_write_config32(dev, 0xe8, 0x00112233);
+
+ /* fwh decode */
+ pci_write_config8(dev, 0xf0, 0x0f);
+
+ /* av disable, sata controller */
+ pci_write_config8(dev, 0xf2, 0xc0);
+
+ /* undocumented */
+ pci_write_config8(dev, 0xa0, 0x20);
+ pci_write_config8(dev, 0xad, 0x03);
+ pci_write_config8(dev, 0xbb, 0x09);
+
+ /* apic1 rout */
+ pci_write_config8(dev, 0xf4, 0x40);
+
+ /* undocumented */
+ pci_write_config8(dev, 0xa0, 0x20);
+ pci_write_config8(dev, 0xad, 0x03);
+ pci_write_config8(dev, 0xbb, 0x09);
+
+ esb6300_enable_serial_irqs(dev);
+
+ esb6300_pci_dma_cfg(dev);
+
+ esb6300_enable_lpc(dev);
+
+ get_option(&pwr_on, "power_on_after_fail");
+ byte = pci_read_config8(dev, 0xa4);
+ byte &= 0xfe;
+ if (!pwr_on) {
+ byte |= 1;
+ }
+ pci_write_config8(dev, 0xa4, byte);
+ printk_info("set power %s after power fail\n", pwr_on?"on":"off");
+
+ /* Set up the PIRQ */
+ esb6300_pirq_init(dev);
+
+ /* Set the state of the gpio lines */
+ esb6300_gpio_init(dev);
+
+ /* Initialize the real time clock */
+ rtc_init(0);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+}
+
+static void esb6300_lpc_read_resources(device_t dev)
+{
+ struct resource *res;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev);
+
+ /* Add the ACPI BAR */
+ res = pci_get_resource(dev, ACPI_BAR);
+
+ /* Add the GPIO BAR */
+ res = pci_get_resource(dev, GPIO_BAR);
+
+ /* Add an extra subtractive resource for both memory and I/O */
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+ res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+ res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+}
+
+static void esb6300_lpc_enable_resources(device_t dev)
+{
+ uint8_t acpi_cntl, gpio_cntl;
+
+ /* Enable the normal pci resources */
+ pci_dev_enable_resources(dev);
+
+ /* Enable the ACPI bar */
+ acpi_cntl = pci_read_config8(dev, 0x44);
+ acpi_cntl |= (1 << 4);
+ pci_write_config8(dev, 0x44, acpi_cntl);
+
+ /* Enable the GPIO bar */
+ gpio_cntl = pci_read_config8(dev, 0x5c);
+ gpio_cntl |= (1 << 4);
+ pci_write_config8(dev, 0x5c, gpio_cntl);
+
+ enable_childrens_resources(dev);
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = 0,
+};
+
+static struct device_operations lpc_ops = {
+ .read_resources = esb6300_lpc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = esb6300_lpc_enable_resources,
+ .init = lpc_init,
+ .scan_bus = scan_static_bus,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver lpc_driver __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_ISA,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300_pci.c b/src/southbridge/intel/esb6300/esb6300_pci.c
new file mode 100644
index 0000000000..1131941728
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_pci.c
@@ -0,0 +1,37 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void pci_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* Clear system errors */
+ word = pci_read_config16(dev, 0x06);
+ word |= 0xf900; /* Clear possible errors */
+ pci_write_config16(dev, 0x06, word);
+
+ word = pci_read_config16(dev, 0x1e);
+ word |= 0xf800; /* Clear possible errors */
+ pci_write_config16(dev, 0x1e, word);
+}
+
+static struct device_operations pci_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pci_init,
+ .scan_bus = pci_scan_bridge,
+ .ops_pci = 0,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_PCI,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_pic.c b/src/southbridge/intel/esb6300/esb6300_pic.c
new file mode 100644
index 0000000000..024c7e2980
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_pic.c
@@ -0,0 +1,109 @@
+/*
+ * (C) 2004 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+
+static void setup_ioapic(device_t dev)
+{
+ int i;
+ unsigned long value_low, value_high;
+ unsigned long ioapic_base = 0xfec10000;
+ volatile unsigned long *l;
+ unsigned interrupts;
+
+ l = (unsigned long *) ioapic_base;
+
+ l[0] = 0x01;
+ interrupts = (l[04] >> 16) & 0xff;
+ for (i = 0; i < interrupts; i++) {
+ l[0] = (i * 2) + 0x10;
+ l[4] = DISABLED;
+ value_low = l[4];
+ l[0] = (i * 2) + 0x11;
+ l[4] = NONE; /* Should this be an address? */
+ value_high = l[4];
+ if (value_low == 0xffffffff) {
+ printk_warning("%s IO APIC not responding.\n",
+ dev_path(dev));
+ return;
+ }
+ }
+}
+
+static void pic_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* Clear system errors */
+ word = pci_read_config16(dev, 0x06);
+ word |= 0xf900; /* Clear possible errors */
+ pci_write_config16(dev, 0x06, word);
+
+ /* enable interrupt lines */
+ pci_write_config8(dev, 0x3c, 0xff);
+
+ /* Setup the ioapic */
+ setup_ioapic(dev);
+}
+
+static void pic_read_resources(device_t dev)
+{
+ struct resource *res;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev);
+
+ /* Report the pic1 mbar resource */
+ res = new_resource(dev, 0x44);
+ res->base = 0xfec10000;
+ res->size = 256;
+ res->limit = res->base + res->size -1;
+ res->align = 8;
+ res->gran = 8;
+ res->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
+ IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+ dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+}
+
+static struct pci_operations lops_pci = {
+ /* Can we set the pci subsystem and device id? */
+ .set_subsystem = 0,
+};
+
+static struct device_operations pci_ops = {
+ .read_resources = pic_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = pic_init,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_PIC1,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_sata.c b/src/southbridge/intel/esb6300/esb6300_sata.c
new file mode 100644
index 0000000000..9d8fb759fc
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_sata.c
@@ -0,0 +1,77 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void sata_init(struct device *dev)
+{
+
+ /* Enable sata devices so the linux sata driver will work */
+ uint16_t word;
+
+ /* Enable SATA devices */
+
+ printk_debug("SATA init\n");
+ /* SATA configuration */
+ pci_write_config8(dev, 0x04, 0x07);
+ pci_write_config8(dev, 0x09, 0x8f);
+
+ /* Set timmings */
+ pci_write_config16(dev, 0x40, 0x0a307);
+ pci_write_config16(dev, 0x42, 0x0a307);
+
+ /* Sync DMA */
+ pci_write_config16(dev, 0x48, 0x000f);
+ pci_write_config16(dev, 0x4a, 0x1111);
+
+ /* 66 mhz */
+ pci_write_config16(dev, 0x54, 0xf00f);
+
+ /* Combine ide - sata configuration */
+ pci_write_config8(dev, 0x90, 0x0);
+
+ /* port 0 & 1 enable */
+ pci_write_config8(dev, 0x92, 0x33);
+
+ /* initialize SATA */
+ pci_write_config16(dev, 0xa0, 0x0018);
+ pci_write_config32(dev, 0xa4, 0x00000264);
+ pci_write_config16(dev, 0xa0, 0x0040);
+ pci_write_config32(dev, 0xa4, 0x00220043);
+
+ printk_debug("SATA Enabled\n");
+}
+
+static void esb6300_sata_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* This value is also visible in usb1, usb2 and smbus functions */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = esb6300_sata_set_subsystem,
+};
+static struct device_operations sata_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = sata_init,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver sata_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_SATA,
+};
+
+static struct pci_driver sata_driver_nr __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_SATA_R,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_smbus.c b/src/southbridge/intel/esb6300/esb6300_smbus.c
new file mode 100644
index 0000000000..6cb6f2d9bb
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_smbus.c
@@ -0,0 +1,45 @@
+#include <device/device.h>
+#include <device/path.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/smbus.h>
+#include <arch/io.h>
+#include "esb6300.h"
+#include "esb6300_smbus.h"
+
+static int lsmbus_read_byte(struct bus *bus, device_t dev, uint8_t address)
+{
+ unsigned device;
+ struct resource *res;
+
+ device = dev->path.u.i2c.device;
+ res = find_resource(bus->dev, 0x20);
+
+ return do_smbus_read_byte(res->base, device, address);
+}
+
+static struct smbus_bus_operations lops_smbus_bus = {
+ .read_byte = lsmbus_read_byte,
+};
+static struct pci_operations lops_pci = {
+ /* The subsystem id follows the ide controller */
+ .set_subsystem = 0,
+};
+static struct device_operations smbus_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = scan_static_bus,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+ .ops_smbus_bus = &lops_smbus_bus,
+};
+
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_SMB,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_smbus.h b/src/southbridge/intel/esb6300/esb6300_smbus.h
new file mode 100644
index 0000000000..861230e130
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_smbus.h
@@ -0,0 +1,105 @@
+#include <device/smbus_def.h>
+
+#define SMBHSTSTAT 0x0
+#define SMBHSTCTL 0x2
+#define SMBHSTCMD 0x3
+#define SMBXMITADD 0x4
+#define SMBHSTDAT0 0x5
+#define SMBHSTDAT1 0x6
+#define SMBBLKDAT 0x7
+#define SMBTRNSADD 0x9
+#define SMBSLVDATA 0xa
+#define SMLINK_PIN_CTL 0xe
+#define SMBUS_PIN_CTL 0xf
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+
+static void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(unsigned smbus_io_base)
+{
+ unsigned loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while(byte & 1);
+ return loops?0:-1;
+}
+
+static int smbus_wait_until_done(unsigned smbus_io_base)
+{
+ unsigned loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0);
+ return loops?0:-1;
+}
+
+static int smbus_wait_until_blk_done(unsigned smbus_io_base)
+{
+ unsigned loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while((byte&(1<<7)) == 0);
+ return loops?0:-1;
+}
+
+static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+ }
+ /* setup transaction */
+ /* disable interrupts */
+ outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
+ /* set the command/address... */
+ outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
+ /* set up for a byte data read */
+ outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
+ /* clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
+
+ /* clear the data byte...*/
+ outb(0, smbus_io_base + SMBHSTDAT0);
+
+ /* start the command */
+ outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+ }
+
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT);
+
+ /* Ignore the In Use Status... */
+ global_status_register &= ~(3 << 5);
+
+ /* read results of transaction */
+ byte = inb(smbus_io_base + SMBHSTDAT0);
+ if (global_status_register != (1 << 1)) {
+ return SMBUS_ERROR;
+ }
+ return byte;
+}
+
diff --git a/src/southbridge/intel/esb6300/esb6300_uhci.c b/src/southbridge/intel/esb6300/esb6300_uhci.c
new file mode 100644
index 0000000000..835a39c2e4
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_uhci.c
@@ -0,0 +1,56 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void uhci_init(struct device *dev)
+{
+ uint32_t cmd;
+
+#if 1
+ printk_debug("UHCI: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+
+
+ printk_debug("done.\n");
+#endif
+
+}
+
+static struct pci_operations lops_pci = {
+ /* The subsystem id follows the ide controller */
+ .set_subsystem = 0,
+};
+
+static struct device_operations uhci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = uhci_init,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver uhci_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_USB,
+};
+
+static struct pci_driver usb2_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_USB2,
+};
+
+static struct pci_driver usb3_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_USB3,
+};
+
diff --git a/src/southbridge/intel/i82801er/i82801er_reset.c b/src/southbridge/intel/i82801er/i82801er_reset.c
index 3d7a4b79b6..fa41756557 100644
--- a/src/southbridge/intel/i82801er/i82801er_reset.c
+++ b/src/southbridge/intel/i82801er/i82801er_reset.c
@@ -1,6 +1,6 @@
#include <arch/io.h>
-void hard_reset(void)
+void i82801er_hard_reset(void)
{
/* Try rebooting through port 0xcf9 */
outb((0 <<3)|(1<<2)|(1<<1), 0xcf9);
diff --git a/src/southbridge/intel/i82870/p64h2_pcibridge.c b/src/southbridge/intel/i82870/p64h2_pcibridge.c
index 6f161e900b..01f871766d 100644
--- a/src/southbridge/intel/i82870/p64h2_pcibridge.c
+++ b/src/southbridge/intel/i82870/p64h2_pcibridge.c
@@ -29,6 +29,7 @@ static struct device_operations pcix_ops = {
.enable_resources = pci_bus_enable_resources,
.init = p64h2_pcix_init,
.scan_bus = pci_scan_bridge,
+ .reset_bus = pci_bus_reset,
};
static struct pci_driver pcix_driver __pci_driver = {
diff --git a/src/southbridge/intel/ich5r/Config.lb b/src/southbridge/intel/ich5r/Config.lb
new file mode 100644
index 0000000000..0bad3f0bf5
--- /dev/null
+++ b/src/southbridge/intel/ich5r/Config.lb
@@ -0,0 +1,11 @@
+config chip.h
+driver ich5r.o
+driver ich5r_uhci.o
+driver ich5r_lpc.o
+driver ich5r_ide.o
+driver ich5r_sata.o
+driver ich5r_ehci.o
+driver ich5r_smbus.o
+driver ich5r_pci.o
+driver ich5r_ac97.o
+object ich5r_watchdog.o
diff --git a/src/southbridge/intel/ich5r/chip.h b/src/southbridge/intel/ich5r/chip.h
new file mode 100644
index 0000000000..b3abeabca7
--- /dev/null
+++ b/src/southbridge/intel/ich5r/chip.h
@@ -0,0 +1,30 @@
+struct southbridge_intel_ich5r_config
+{
+
+#define ICH5R_GPIO_USE_MASK 0x03
+#define ICH5R_GPIO_USE_DEFAULT 0x00
+#define ICH5R_GPIO_USE_AS_NATIVE 0x01
+#define ICH5R_GPIO_USE_AS_GPIO 0x02
+
+#define ICH5R_GPIO_SEL_MASK 0x0c
+#define ICH5R_GPIO_SEL_DEFAULT 0x00
+#define ICH5R_GPIO_SEL_OUTPUT 0x04
+#define ICH5R_GPIO_SEL_INPUT 0x08
+
+#define ICH5R_GPIO_LVL_MASK 0x30
+#define ICH5R_GPIO_LVL_DEFAULT 0x00
+#define ICH5R_GPIO_LVL_LOW 0x10
+#define ICH5R_GPIO_LVL_HIGH 0x20
+#define ICH5R_GPIO_LVL_BLINK 0x30
+
+#define ICH5R_GPIO_INV_MASK 0xc0
+#define ICH5R_GPIO_INV_DEFAULT 0x00
+#define ICH5R_GPIO_INV_OFF 0x40
+#define ICH5R_GPIO_INV_ON 0x80
+
+ /* GPIO use select */
+ unsigned char gpio[64];
+ unsigned int pirq_a_d;
+ unsigned int pirq_e_h;
+};
+extern struct chip_operations southbridge_intel_ich5r_ops;
diff --git a/src/southbridge/intel/ich5r/ich5r.c b/src/southbridge/intel/ich5r/ich5r.c
new file mode 100644
index 0000000000..1b65465234
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r.c
@@ -0,0 +1,48 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "ich5r.h"
+
+void ich5r_enable(device_t dev)
+{
+ device_t lpc_dev;
+ unsigned index = 0;
+ uint16_t reg_old, reg;
+
+ /* See if we are on the behind the ich5r pci bridge */
+ lpc_dev = dev_find_slot(dev->bus->secondary, PCI_DEVFN(0x1f, 0));
+ if((dev->path.u.pci.devfn &0xf8)== 0xf8) {
+ index = dev->path.u.pci.devfn & 7;
+ }
+ else if((dev->path.u.pci.devfn &0xf8)== 0xe8) {
+ index = (dev->path.u.pci.devfn & 7) +8;
+ }
+ if ((!lpc_dev) || (index >= 16) || ((1<<index)&0x3091)) {
+ return;
+ }
+ if ((lpc_dev->vendor != PCI_VENDOR_ID_INTEL) ||
+ (lpc_dev->device != PCI_DEVICE_ID_INTEL_82801ER_ISA)) {
+ uint32_t id;
+ id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
+ if (id != (PCI_VENDOR_ID_INTEL |
+ (PCI_DEVICE_ID_INTEL_82801ER_ISA << 16))) {
+ return;
+ }
+ }
+
+ reg = reg_old = pci_read_config16(lpc_dev, 0xf2);
+ reg &= ~(1 << index);
+ if (!dev->enabled) {
+ reg |= (1 << index);
+ }
+ if (reg != reg_old) {
+ pci_write_config16(lpc_dev, 0xf2, reg);
+ }
+
+}
+
+struct chip_operations southbridge_intel_ich5r_ops = {
+ CHIP_NAME("INTEL 82801ER")
+ .enable_dev = ich5r_enable,
+};
diff --git a/src/southbridge/intel/ich5r/ich5r.h b/src/southbridge/intel/ich5r/ich5r.h
new file mode 100644
index 0000000000..28572c9c27
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r.h
@@ -0,0 +1,7 @@
+#ifndef ICH5R_H
+#define ICH5R_H
+
+#include "chip.h"
+void ich5r_enable(device_t dev);
+
+#endif /* ICH5R_H */
diff --git a/src/southbridge/intel/ich5r/ich5r_ac97.c b/src/southbridge/intel/ich5r/ich5r_ac97.c
new file mode 100644
index 0000000000..17d924b196
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_ac97.c
@@ -0,0 +1,37 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ich5r.h"
+
+static void ac97_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* Write the subsystem vendor and device id */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = ac97_set_subsystem,
+};
+static struct device_operations ac97_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = 0,
+ .enable = ich5r_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ac97_audio_driver __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_AC97_AUDIO,
+};
+static struct pci_driver ac97_modem_driver __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_AC97_MODEM,
+};
diff --git a/src/southbridge/intel/ich5r/ich5r_early_smbus.c b/src/southbridge/intel/ich5r/ich5r_early_smbus.c
new file mode 100644
index 0000000000..6880fde126
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_early_smbus.c
@@ -0,0 +1,130 @@
+#include "ich5r_smbus.h"
+
+#define SMBUS_IO_BASE 0x0f00
+
+static void enable_smbus(void)
+{
+ device_t dev;
+ dev = pci_locate_device(PCI_ID(0x8086, 0x24d3), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("SMBUS controller not found\r\n");
+ }
+ uint8_t enable;
+ print_spew("SMBus controller enabled\r\n");
+ pci_write_config32(dev, 0x20, SMBUS_IO_BASE | 1);
+ pci_write_config8(dev, 0x40, 1);
+ pci_write_config8(dev, 0x4, 1);
+ /* SMBALERT_DIS */
+ pci_write_config8(dev, 0x11, 4);
+
+ /* Disable interrupt generation */
+ outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+ dev = pci_locate_device(PCI_ID(0x8086, 0x24d0), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("ISA bridge not found\r\n");
+ }
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+ return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
+}
+
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+ if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) {
+ return;
+ }
+#if 0
+ /* setup transaction */
+ /* disable interrupts */
+ outw(inw(SMBUS_IO_BASE + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)),
+ SMBUS_IO_BASE + SMBGCTL);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADDR);
+ outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+ /* set up for a byte data write */ /* FIXME */
+ outw((inw(SMBUS_IO_BASE + SMBGCTL) & ~7) | (0x1), SMBUS_IO_BASE + SMBGCTL);
+ /* clear any lingering errors, so the transaction will run */
+ /* Do I need to write the bits to a 1 to clear an error? */
+ outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS);
+
+ /* clear the data word...*/
+ outw(val, SMBUS_IO_BASE + SMBHSTDAT);
+
+ /* start the command */
+ outw((inw(SMBUS_IO_BASE + SMBGCTL) | (1 << 3)), SMBUS_IO_BASE + SMBGCTL);
+
+ /* poll for transaction completion */
+ smbus_wait_until_done(SMBUS_IO_BASE);
+#endif
+ return;
+}
+
+static int smbus_write_block(unsigned device, unsigned length, unsigned cmd,
+ unsigned data1, unsigned data2)
+{
+ unsigned char global_control_register;
+ unsigned char global_status_register;
+ unsigned char byte;
+ unsigned char stat;
+ int i;
+
+ /* chear the PM timeout flags, SECOND_TO_STS */
+ outw(inw(0x0400 + 0x66), 0x0400 + 0x66);
+
+ if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) {
+ return -2;
+ }
+
+ /* setup transaction */
+ /* Obtain ownership */
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+ for(stat=0;(stat&0x40)==0;) {
+ stat = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+ /* clear the done bit */
+ outb(0x80, SMBUS_IO_BASE + SMBHSTSTAT);
+ /* disable interrupts */
+ outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1), SMBUS_IO_BASE + SMBXMITADD);
+
+ /* set the command address */
+ outb(cmd & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+
+ /* set the block length */
+ outb(length & 0xFF, SMBUS_IO_BASE + SMBHSTDAT0);
+
+ /* try sending out the first byte of data here */
+ byte=(data1>>(0))&0x0ff;
+ outb(byte,SMBUS_IO_BASE + SMBBLKDAT);
+ /* issue a block write command */
+ outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x5 << 2) | 0x40,
+ SMBUS_IO_BASE + SMBHSTCTL);
+
+ for(i=0;i<length;i++) {
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_blk_done(SMBUS_IO_BASE) < 0) {
+ return -3;
+ }
+
+ /* load the next byte */
+ if(i>3)
+ byte=(data2>>(i%4))&0x0ff;
+ else
+ byte=(data1>>(i))&0x0ff;
+ outb(byte,SMBUS_IO_BASE + SMBBLKDAT);
+
+ /* clear the done bit */
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
+ SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+
+ print_debug("SMBUS Block complete\r\n");
+ return 0;
+}
+
diff --git a/src/southbridge/intel/ich5r/ich5r_ehci.c b/src/southbridge/intel/ich5r/ich5r_ehci.c
new file mode 100644
index 0000000000..d1650c1385
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_ehci.c
@@ -0,0 +1,50 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ich5r.h"
+
+static void ehci_init(struct device *dev)
+{
+ uint32_t cmd;
+
+ printk_debug("EHCI: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+
+ printk_debug("done.\n");
+}
+
+static void ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ uint8_t access_cntl;
+ access_cntl = pci_read_config8(dev, 0x80);
+ /* Enable writes to protected registers */
+ pci_write_config8(dev, 0x80, access_cntl | 1);
+ /* Write the subsystem vendor and device id */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+ /* Restore protection */
+ pci_write_config8(dev, 0x80, access_cntl);
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = &ehci_set_subsystem,
+};
+static struct device_operations ehci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ehci_init,
+ .scan_bus = 0,
+ .enable = ich5r_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ehci_driver __pci_driver = {
+ .ops = &ehci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_EHCI,
+};
diff --git a/src/southbridge/intel/ich5r/ich5r_ide.c b/src/southbridge/intel/ich5r/ich5r_ide.c
new file mode 100644
index 0000000000..7bfd92555c
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_ide.c
@@ -0,0 +1,44 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ich5r.h"
+
+static void ide_init(struct device *dev)
+{
+
+ /* Enable IDE devices and timmings */
+ pci_write_config16(dev, 0x40, 0x0a307);
+ pci_write_config16(dev, 0x42, 0x0a307);
+ pci_write_config8(dev, 0x48, 0x05);
+ pci_write_config16(dev, 0x4a, 0x0101);
+ pci_write_config16(dev, 0x54, 0x5055);
+ printk_debug("IDE Enabled\n");
+}
+
+static void ich5r_ide_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* This value is also visible in uchi[0-2] and smbus functions */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = ich5r_ide_set_subsystem,
+};
+static struct device_operations ide_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ide_init,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ide_driver __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_IDE,
+};
+
diff --git a/src/southbridge/intel/ich5r/ich5r_lpc.c b/src/southbridge/intel/ich5r/ich5r_lpc.c
new file mode 100644
index 0000000000..d9d98891ad
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_lpc.c
@@ -0,0 +1,369 @@
+/*
+ * (C) 2004 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <arch/io.h>
+#include "ich5r.h"
+
+#define ACPI_BAR 0x40
+#define GPIO_BAR 0x58
+
+#define NMI_OFF 0
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON 1
+
+#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
+#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
+#endif
+
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+
+static void setup_ioapic(void)
+{
+ int i;
+ unsigned long value_low, value_high;
+ unsigned long ioapic_base = 0xfec00000;
+ volatile unsigned long *l;
+ unsigned interrupts;
+
+ l = (unsigned long *) ioapic_base;
+
+ l[0] = 0x01;
+ interrupts = (l[04] >> 16) & 0xff;
+ for (i = 0; i < interrupts; i++) {
+ l[0] = (i * 2) + 0x10;
+ l[4] = DISABLED;
+ value_low = l[4];
+ l[0] = (i * 2) + 0x11;
+ l[4] = NONE; /* Should this be an address? */
+ value_high = l[4];
+ if (value_low == 0xffffffff) {
+ printk_warning("IO APIC not responding.\n");
+ return;
+ }
+ }
+
+ /* Put the ioapic in virtual wire mode */
+ l[0] = 0 + 0x10;
+ l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
+}
+
+#define SERIRQ_CNTL 0x64
+static void ich5r_enable_serial_irqs(device_t dev)
+{
+ /* set packet length and toggle silent mode bit */
+ pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
+ pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
+}
+
+#define PCI_DMA_CFG 0x90
+static void ich5r_pci_dma_cfg(device_t dev)
+{
+ /* Set PCI DMA CFG to lpc I/F DMA */
+ pci_write_config16(dev, PCI_DMA_CFG, 0xfcff);
+}
+
+#define LPC_EN 0xe6
+static void ich5r_enable_lpc(device_t dev)
+{
+ /* lpc i/f enable */
+ pci_write_config8(dev, LPC_EN, 0x0d);
+}
+
+typedef struct southbridge_intel_ich5r_config config_t;
+
+static void set_ich5r_gpio_use_sel(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_use_sel, gpio_use_sel2;
+ int i;
+
+ gpio_use_sel = 0x1A003180;
+ gpio_use_sel2 = 0x00000007;
+ for(i = 0; i < 64; i++) {
+ int val;
+ switch(config->gpio[i] & ICH5R_GPIO_USE_MASK) {
+ case ICH5R_GPIO_USE_AS_NATIVE: val = 0; break;
+ case ICH5R_GPIO_USE_AS_GPIO: val = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_use_sel &= ~( 1 << i);
+ gpio_use_sel |= (val << i);
+ } else {
+ gpio_use_sel2 &= ~( 1 << (i - 32));
+ gpio_use_sel2 |= (val << (i - 32));
+ }
+ }
+ outl(gpio_use_sel, res->base + 0x00);
+ outl(gpio_use_sel2, res->base + 0x30);
+}
+
+static void set_ich5r_gpio_direction(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_io_sel, gpio_io_sel2;
+ int i;
+
+ gpio_io_sel = 0x0000ffff;
+ gpio_io_sel2 = 0x00000300;
+ for(i = 0; i < 64; i++) {
+ int val;
+ switch(config->gpio[i] & ICH5R_GPIO_SEL_MASK) {
+ case ICH5R_GPIO_SEL_OUTPUT: val = 0; break;
+ case ICH5R_GPIO_SEL_INPUT: val = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_io_sel &= ~( 1 << i);
+ gpio_io_sel |= (val << i);
+ } else {
+ gpio_io_sel2 &= ~( 1 << (i - 32));
+ gpio_io_sel2 |= (val << (i - 32));
+ }
+ }
+ outl(gpio_io_sel, res->base + 0x04);
+ outl(gpio_io_sel2, res->base + 0x34);
+}
+
+static void set_ich5r_gpio_level(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_lvl, gpio_lvl2;
+ uint32_t gpio_blink;
+ int i;
+
+ gpio_lvl = 0x1b3f0000;
+ gpio_blink = 0x00040000;
+ gpio_lvl2 = 0x00030207;
+ for(i = 0; i < 64; i++) {
+ int val, blink;
+ switch(config->gpio[i] & ICH5R_GPIO_LVL_MASK) {
+ case ICH5R_GPIO_LVL_LOW: val = 0; blink = 0; break;
+ case ICH5R_GPIO_LVL_HIGH: val = 1; blink = 0; break;
+ case ICH5R_GPIO_LVL_BLINK: val = 1; blink = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_lvl &= ~( 1 << i);
+ gpio_blink &= ~( 1 << i);
+ gpio_lvl |= ( val << i);
+ gpio_blink |= (blink << i);
+ } else {
+ gpio_lvl2 &= ~( 1 << (i - 32));
+ gpio_lvl2 |= (val << (i - 32));
+ }
+ }
+ outl(gpio_lvl, res->base + 0x0c);
+ outl(gpio_blink, res->base + 0x18);
+ outl(gpio_lvl2, res->base + 0x38);
+}
+
+static void set_ich5r_gpio_inv(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_inv;
+ int i;
+
+ gpio_inv = 0x00000000;
+ for(i = 0; i < 32; i++) {
+ int val;
+ switch(config->gpio[i] & ICH5R_GPIO_INV_MASK) {
+ case ICH5R_GPIO_INV_OFF: val = 0; break;
+ case ICH5R_GPIO_INV_ON: val = 1; break;
+ default:
+ continue;
+ }
+ gpio_inv &= ~( 1 << i);
+ gpio_inv |= (val << i);
+ }
+ outl(gpio_inv, res->base + 0x2c);
+}
+
+static void ich5r_pirq_init(device_t dev)
+{
+ config_t *config;
+
+ /* Get the chip configuration */
+ config = dev->chip_info;
+
+ if(config->pirq_a_d) {
+ pci_write_config32(dev, 0x60, config->pirq_a_d);
+ }
+ if(config->pirq_e_h) {
+ pci_write_config32(dev, 0x68, config->pirq_e_h);
+ }
+}
+
+
+static void ich5r_gpio_init(device_t dev)
+{
+ struct resource *res;
+ config_t *config;
+
+ /* Skip if I don't have any configuration */
+ if (!dev->chip_info) {
+ return;
+ }
+ /* The programmer is responsible for ensuring
+ * a valid gpio configuration.
+ */
+
+ /* Get the chip configuration */
+ config = dev->chip_info;
+ /* Find the GPIO bar */
+ res = find_resource(dev, GPIO_BAR);
+ if (!res) {
+ return;
+ }
+
+ /* Set the use selects */
+ set_ich5r_gpio_use_sel(dev, res, config);
+
+ /* Set the IO direction */
+ set_ich5r_gpio_direction(dev, res, config);
+
+ /* Setup the input inverters */
+ set_ich5r_gpio_inv(dev, res, config);
+
+ /* Set the value on the GPIO output pins */
+ set_ich5r_gpio_level(dev, res, config);
+
+}
+
+
+static void lpc_init(struct device *dev)
+{
+ uint8_t byte;
+ uint32_t value;
+ int pwr_on=MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
+
+ /* IO APIC initialization */
+ value = pci_read_config32(dev, 0xd0);
+ value |= (1 << 8)|(1<<7)|(1<<1);
+ pci_write_config32(dev, 0xd0, value);
+ value = pci_read_config32(dev, 0xd4);
+ value |= (1<<1);
+ pci_write_config32(dev, 0xd4, value);
+ setup_ioapic();
+
+ ich5r_enable_serial_irqs(dev);
+
+ ich5r_pci_dma_cfg(dev);
+
+ ich5r_enable_lpc(dev);
+
+ /* Clear SATA to non raid */
+ pci_write_config8(dev, 0xae, 0x00);
+
+ get_option(&pwr_on, "power_on_after_fail");
+ byte = pci_read_config8(dev, 0xa4);
+ byte &= 0xfe;
+ if (!pwr_on) {
+ byte |= 1;
+ }
+ pci_write_config8(dev, 0xa4, byte);
+ printk_info("set power %s after power fail\n", pwr_on?"on":"off");
+
+ /* Set up the PIRQ */
+ ich5r_pirq_init(dev);
+
+ /* Set the state of the gpio lines */
+ ich5r_gpio_init(dev);
+
+ /* Initialize the real time clock */
+ rtc_init(0);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+
+ /* Disable IDE (needed when sata is enabled) */
+ pci_write_config8(dev, 0xf2, 0x60);
+
+}
+
+static void ich5r_lpc_read_resources(device_t dev)
+{
+ struct resource *res;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev);
+
+ /* Add the ACPI BAR */
+ res = pci_get_resource(dev, ACPI_BAR);
+
+ /* Add the GPIO BAR */
+ res = pci_get_resource(dev, GPIO_BAR);
+
+ /* Add an extra subtractive resource for both memory and I/O */
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+ res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+ res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+}
+
+static void ich5r_lpc_enable_resources(device_t dev)
+{
+ uint8_t acpi_cntl, gpio_cntl;
+
+ /* Enable the normal pci resources */
+ pci_dev_enable_resources(dev);
+
+ /* Enable the ACPI bar */
+ acpi_cntl = pci_read_config8(dev, 0x44);
+ acpi_cntl |= (1 << 4);
+ pci_write_config8(dev, 0x44, acpi_cntl);
+
+ /* Enable the GPIO bar */
+ gpio_cntl = pci_read_config8(dev, 0x5c);
+ gpio_cntl |= (1 << 4);
+ pci_write_config8(dev, 0x5c, gpio_cntl);
+
+ enable_childrens_resources(dev);
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = 0,
+};
+
+static struct device_operations lpc_ops = {
+ .read_resources = ich5r_lpc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = ich5r_lpc_enable_resources,
+ .init = lpc_init,
+ .scan_bus = scan_static_bus,
+ .enable = ich5r_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver lpc_driver __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_ISA,
+};
diff --git a/src/southbridge/intel/ich5r/ich5r_pci.c b/src/southbridge/intel/ich5r/ich5r_pci.c
new file mode 100644
index 0000000000..d2c94c778e
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_pci.c
@@ -0,0 +1,37 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ich5r.h"
+
+static void pci_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* Clear system errors */
+ word = pci_read_config16(dev, 0x06);
+ word |= 0xf900; /* Clear possible errors */
+ pci_write_config16(dev, 0x06, word);
+
+ word = pci_read_config16(dev, 0x1e);
+ word |= 0xf800; /* Clear possible errors */
+ pci_write_config16(dev, 0x1e, word);
+}
+
+static struct device_operations pci_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pci_init,
+ .scan_bus = pci_scan_bridge,
+ .ops_pci = 0,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_PCI,
+};
+
diff --git a/src/southbridge/intel/ich5r/ich5r_sata.c b/src/southbridge/intel/ich5r/ich5r_sata.c
new file mode 100644
index 0000000000..803d8789cf
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_sata.c
@@ -0,0 +1,63 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ich5r.h"
+
+static void sata_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ printk_debug("SATA init\n");
+ /* SATA configuration */
+ pci_write_config8(dev, 0x04, 0x07);
+ pci_write_config8(dev, 0x09, 0x8f);
+
+ /* Set timmings */
+ pci_write_config16(dev, 0x40, 0x0a307);
+ pci_write_config16(dev, 0x42, 0x0a307);
+
+ /* Sync DMA */
+ pci_write_config16(dev, 0x48, 0x000f);
+ pci_write_config16(dev, 0x4a, 0x1111);
+
+ /* 66 mhz */
+ pci_write_config16(dev, 0x54, 0xf00f);
+
+ /* Combine ide - sata configuration */
+ pci_write_config8(dev, 0x90, 0x0);
+
+ /* port 0 & 1 enable */
+ pci_write_config8(dev, 0x92, 0x33);
+
+ /* initialize SATA */
+ pci_write_config16(dev, 0xa0, 0x0018);
+ pci_write_config32(dev, 0xa4, 0x00000264);
+ pci_write_config16(dev, 0xa0, 0x0040);
+ pci_write_config32(dev, 0xa4, 0x00220043);
+
+}
+
+static struct device_operations sata_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = sata_init,
+ .scan_bus = 0,
+ .ops_pci = 0,
+};
+
+static struct pci_driver sata_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_1F2_R,
+};
+
+static struct pci_driver sata_driver_nr __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_1F2,
+};
+
diff --git a/src/southbridge/intel/ich5r/ich5r_smbus.c b/src/southbridge/intel/ich5r/ich5r_smbus.c
new file mode 100644
index 0000000000..3337a65b15
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_smbus.c
@@ -0,0 +1,45 @@
+#include <device/device.h>
+#include <device/path.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/smbus.h>
+#include <arch/io.h>
+#include "ich5r.h"
+#include "ich5r_smbus.h"
+
+static int lsmbus_read_byte(struct bus *bus, device_t dev, uint8_t address)
+{
+ unsigned device;
+ struct resource *res;
+
+ device = dev->path.u.i2c.device;
+ res = find_resource(bus->dev, 0x20);
+
+ return do_smbus_read_byte(res->base, device, address);
+}
+
+static struct smbus_bus_operations lops_smbus_bus = {
+ .read_byte = lsmbus_read_byte,
+};
+static struct pci_operations lops_pci = {
+ /* The subsystem id follows the ide controller */
+ .set_subsystem = 0,
+};
+static struct device_operations smbus_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = scan_static_bus,
+ .enable = ich5r_enable,
+ .ops_pci = &lops_pci,
+ .ops_smbus_bus = &lops_smbus_bus,
+};
+
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_SMB,
+};
+
diff --git a/src/southbridge/intel/ich5r/ich5r_smbus.h b/src/southbridge/intel/ich5r/ich5r_smbus.h
new file mode 100644
index 0000000000..861230e130
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_smbus.h
@@ -0,0 +1,105 @@
+#include <device/smbus_def.h>
+
+#define SMBHSTSTAT 0x0
+#define SMBHSTCTL 0x2
+#define SMBHSTCMD 0x3
+#define SMBXMITADD 0x4
+#define SMBHSTDAT0 0x5
+#define SMBHSTDAT1 0x6
+#define SMBBLKDAT 0x7
+#define SMBTRNSADD 0x9
+#define SMBSLVDATA 0xa
+#define SMLINK_PIN_CTL 0xe
+#define SMBUS_PIN_CTL 0xf
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+
+static void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(unsigned smbus_io_base)
+{
+ unsigned loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while(byte & 1);
+ return loops?0:-1;
+}
+
+static int smbus_wait_until_done(unsigned smbus_io_base)
+{
+ unsigned loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while((byte & 1) || (byte & ~((1<<6)|(1<<0))) == 0);
+ return loops?0:-1;
+}
+
+static int smbus_wait_until_blk_done(unsigned smbus_io_base)
+{
+ unsigned loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while((byte&(1<<7)) == 0);
+ return loops?0:-1;
+}
+
+static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+ }
+ /* setup transaction */
+ /* disable interrupts */
+ outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
+ /* set the command/address... */
+ outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
+ /* set up for a byte data read */
+ outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
+ /* clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
+
+ /* clear the data byte...*/
+ outb(0, smbus_io_base + SMBHSTDAT0);
+
+ /* start the command */
+ outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+ }
+
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT);
+
+ /* Ignore the In Use Status... */
+ global_status_register &= ~(3 << 5);
+
+ /* read results of transaction */
+ byte = inb(smbus_io_base + SMBHSTDAT0);
+ if (global_status_register != (1 << 1)) {
+ return SMBUS_ERROR;
+ }
+ return byte;
+}
+
diff --git a/src/southbridge/intel/ich5r/ich5r_uhci.c b/src/southbridge/intel/ich5r/ich5r_uhci.c
new file mode 100644
index 0000000000..ad4ae978cf
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_uhci.c
@@ -0,0 +1,56 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ich5r.h"
+
+static void uhci_init(struct device *dev)
+{
+ uint32_t cmd;
+
+#if 1
+ printk_debug("UHCI: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+
+
+ printk_debug("done.\n");
+#endif
+
+}
+
+static struct pci_operations lops_pci = {
+ /* The subsystem id follows the ide controller */
+ .set_subsystem = 0,
+};
+
+static struct device_operations uhci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = uhci_init,
+ .scan_bus = 0,
+ .enable = ich5r_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver uhci_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_USB,
+};
+
+static struct pci_driver usb2_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_USB2,
+};
+
+static struct pci_driver usb3_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801ER_USB3,
+};
+
diff --git a/src/southbridge/intel/ich5r/ich5r_watchdog.c b/src/southbridge/intel/ich5r/ich5r_watchdog.c
new file mode 100644
index 0000000000..c9c09f5896
--- /dev/null
+++ b/src/southbridge/intel/ich5r/ich5r_watchdog.c
@@ -0,0 +1,28 @@
+#include <console/console.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+
+void watchdog_off(void)
+{
+ device_t dev;
+ unsigned long value,base;
+
+ /* turn off the ICH5 watchdog */
+ dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
+ /* Enable I/O space */
+ value = pci_read_config16(dev, 0x04);
+ value |= (1 << 10);
+ pci_write_config16(dev, 0x04, value);
+ /* Get TCO base */
+ base = (pci_read_config32(dev, 0x40) & 0x0fffe) + 0x60;
+ /* Disable the watchdog timer */
+ value = inw(base + 0x08);
+ value |= 1 << 11;
+ outw(value, base + 0x08);
+ /* Clear TCO timeout status */
+ outw(0x0008, base + 0x04);
+ outw(0x0002, base + 0x06);
+ printk_debug("Watchdog ICH5 disabled\r\n");
+}
+
diff --git a/src/southbridge/intel/pxhd/Config.lb b/src/southbridge/intel/pxhd/Config.lb
new file mode 100644
index 0000000000..349b8dd624
--- /dev/null
+++ b/src/southbridge/intel/pxhd/Config.lb
@@ -0,0 +1,2 @@
+config chip.h
+driver pxhd_bridge.o
diff --git a/src/southbridge/intel/pxhd/chip.h b/src/southbridge/intel/pxhd/chip.h
new file mode 100644
index 0000000000..516f1df7d2
--- /dev/null
+++ b/src/southbridge/intel/pxhd/chip.h
@@ -0,0 +1,5 @@
+struct southbridge_intel_pxhd_config
+{
+ /* nothing */
+};
+struct chip_operations southbridge_intel_pxhd_ops;
diff --git a/src/southbridge/intel/pxhd/pxhd.h b/src/southbridge/intel/pxhd/pxhd.h
new file mode 100644
index 0000000000..c3e6ce5cd7
--- /dev/null
+++ b/src/southbridge/intel/pxhd/pxhd.h
@@ -0,0 +1,6 @@
+#ifndef PXHD_H
+#define PXHD_H
+
+#include "chip.h"
+
+#endif /* PXHD_H */
diff --git a/src/southbridge/intel/pxhd/pxhd_bridge.c b/src/southbridge/intel/pxhd/pxhd_bridge.c
new file mode 100644
index 0000000000..bceca29db9
--- /dev/null
+++ b/src/southbridge/intel/pxhd/pxhd_bridge.c
@@ -0,0 +1,258 @@
+/*
+ * (C) 2003-2004 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/pcix.h>
+#include <pc80/mc146818rtc.h>
+#include <delay.h>
+#include "pxhd.h"
+
+static void pxhd_enable(device_t dev)
+{
+ device_t bridge;
+ uint16_t value;
+ if ((dev->path.u.pci.devfn & 1) == 0) {
+ /* Can we enable/disable the bridges? */
+ return;
+ }
+ bridge = dev_find_slot(dev->bus->secondary, dev->path.u.pci.devfn & ~1);
+ if (!bridge) {
+ printk_err("Cannot find bridge for ioapic: %s\n",
+ dev_path(dev));
+ return;
+ }
+ value = pci_read_config16(bridge, 0x40);
+ value &= ~(1 << 13);
+ if (!dev->enabled) {
+ value |= (1 << 13);
+ }
+ pci_write_config16(bridge, 0x40, value);
+}
+
+
+#define NMI_OFF 0
+
+static unsigned int pxhd_scan_bridge(device_t dev, unsigned int max)
+{
+ int bus_100Mhz = 0;
+
+ dev->link[0].dev = dev;
+ dev->links = 1;
+
+ get_option(&bus_100Mhz, "pxhd_bus_speed_100");
+ if(bus_100Mhz) {
+ uint16_t word;
+
+ printk_debug("setting pxhd bus to 100 Mhz\n");
+ /* set to pcix 100 mhz */
+ word = pci_read_config16(dev, 0x40);
+ word &= ~(3 << 14);
+ word |= (1 << 14);
+ word &= ~(3 << 9);
+ word |= (2 << 9);
+ pci_write_config16(dev, 0x40, word);
+
+ /* reset the bus to make the new frequencies effective */
+ pci_bus_reset(&dev->link[0]);
+ }
+ return pcix_scan_bridge(dev, max);
+}
+static void pcix_init(device_t dev)
+{
+ uint32_t dword;
+ uint16_t word;
+ uint8_t byte;
+ int nmi_option;
+
+ /* Bridge control ISA enable */
+ pci_write_config8(dev, 0x3e, 0x07);
+
+#if 0
+
+ /* Enable memory write and invalidate ??? */
+ byte = pci_read_config8(dev, 0x04);
+ byte |= 0x10;
+ pci_write_config8(dev, 0x04, byte);
+
+ /* Set drive strength */
+ word = pci_read_config16(dev, 0xe0);
+ word = 0x0404;
+ pci_write_config16(dev, 0xe0, word);
+ word = pci_read_config16(dev, 0xe4);
+ word = 0x0404;
+ pci_write_config16(dev, 0xe4, word);
+
+ /* Set impedance */
+ word = pci_read_config16(dev, 0xe8);
+ word = 0x0404;
+ pci_write_config16(dev, 0xe8, word);
+
+ /* Set discard unrequested prefetch data */
+ word = pci_read_config16(dev, 0x4c);
+ word |= 1;
+ pci_write_config16(dev, 0x4c, word);
+
+ /* Set split transaction limits */
+ word = pci_read_config16(dev, 0xa8);
+ pci_write_config16(dev, 0xaa, word);
+ word = pci_read_config16(dev, 0xac);
+ pci_write_config16(dev, 0xae, word);
+
+ /* Set up error reporting, enable all */
+ /* system error enable */
+ dword = pci_read_config32(dev, 0x04);
+ dword |= (1<<8);
+ pci_write_config32(dev, 0x04, dword);
+
+ /* system and error parity enable */
+ dword = pci_read_config32(dev, 0x3c);
+ dword |= (3<<16);
+ pci_write_config32(dev, 0x3c, dword);
+
+ /* NMI enable */
+ nmi_option = NMI_OFF;
+ get_option(&nmi_option, "nmi");
+ if(nmi_option) {
+ dword = pci_read_config32(dev, 0x44);
+ dword |= (1<<0);
+ pci_write_config32(dev, 0x44, dword);
+ }
+
+ /* Set up CRC flood enable */
+ dword = pci_read_config32(dev, 0xc0);
+ if(dword) { /* do device A only */
+ dword = pci_read_config32(dev, 0xc4);
+ dword |= (1<<1);
+ pci_write_config32(dev, 0xc4, dword);
+ dword = pci_read_config32(dev, 0xc8);
+ dword |= (1<<1);
+ pci_write_config32(dev, 0xc8, dword);
+ }
+
+ return;
+#endif
+}
+
+static struct device_operations pcix_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pcix_init,
+ .scan_bus = pxhd_scan_bridge,
+ .reset_bus = pci_bus_reset,
+ .ops_pci = 0,
+};
+
+static struct pci_driver pcix_driver __pci_driver = {
+ .ops = &pcix_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x0329,
+};
+
+static struct pci_driver pcix_driver2 __pci_driver = {
+ .ops = &pcix_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x032a,
+};
+
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+ /* IO-APIC virtual wire mode configuration */
+ /* mask, trigger, polarity, destination, delivery, vector */
+
+static void setup_ioapic(device_t dev)
+{
+ int i;
+ unsigned long value_low, value_high;
+ unsigned long ioapic_base;
+ volatile unsigned long *l;
+ unsigned interrupts;
+
+ ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
+ l = (unsigned long *) ioapic_base;
+
+ /* Enable front side bus delivery */
+ l[0] = 0x03;
+ l[4] = 1;
+
+ l[0] = 0x01;
+ interrupts = (l[04] >> 16) & 0xff;
+ for (i = 0; i < interrupts; i++) {
+ l[0] = (i * 2) + 0x10;
+ l[4] = DISABLED;
+ value_low = l[4];
+ l[0] = (i * 2) + 0x11;
+ l[4] = NONE; /* Should this be an address? */
+ value_high = l[4];
+ if (value_low == 0xffffffff) {
+ printk_warning("IO APIC not responding.\n");
+ return;
+ }
+ }
+}
+
+static void ioapic_init(device_t dev)
+{
+ uint32_t value;
+ /* Enable bus mastering so IOAPICs work */
+ value = pci_read_config16(dev, PCI_COMMAND);
+ value |= PCI_COMMAND_MASTER;
+ pci_write_config16(dev, PCI_COMMAND, value);
+
+ setup_ioapic(dev);
+}
+
+static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations intel_ops_pci = {
+ .set_subsystem = intel_set_subsystem,
+};
+
+static struct device_operations ioapic_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ioapic_init,
+ .scan_bus = 0,
+ .enable = pxhd_enable,
+ .ops_pci = &intel_ops_pci,
+};
+
+static struct pci_driver ioapic_driver __pci_driver = {
+ .ops = &ioapic_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x0326,
+
+};
+
+static struct pci_driver ioapic2_driver __pci_driver = {
+ .ops = &ioapic_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x0327,
+
+};
+
+struct chip_operations southbridge_intel_pxhd_ops = {
+ CHIP_NAME("PXHD")
+ .enable_dev = pxhd_enable,
+};