diff options
Diffstat (limited to 'src/southbridge/intel/pxhd')
-rw-r--r-- | src/southbridge/intel/pxhd/Config.lb | 2 | ||||
-rw-r--r-- | src/southbridge/intel/pxhd/chip.h | 5 | ||||
-rw-r--r-- | src/southbridge/intel/pxhd/pxhd.h | 6 | ||||
-rw-r--r-- | src/southbridge/intel/pxhd/pxhd_bridge.c | 258 |
4 files changed, 271 insertions, 0 deletions
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, +}; |