diff options
-rw-r--r-- | src/southbridge/via/vt8231/vt8231_acpi.c | 44 | ||||
-rw-r--r-- | src/southbridge/via/vt8231/vt8231_ide.c | 108 | ||||
-rw-r--r-- | src/southbridge/via/vt8231/vt8231_lpc.c | 154 | ||||
-rw-r--r-- | src/southbridge/via/vt8231/vt8231_nic.c | 37 | ||||
-rw-r--r-- | src/southbridge/via/vt8231/vt8231_usb.c | 52 |
5 files changed, 395 insertions, 0 deletions
diff --git a/src/southbridge/via/vt8231/vt8231_acpi.c b/src/southbridge/via/vt8231/vt8231_acpi.c new file mode 100644 index 0000000000..40f47b8367 --- /dev/null +++ b/src/southbridge/via/vt8231/vt8231_acpi.c @@ -0,0 +1,44 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.h> +#include <device/pci_ids.h> +#include "vt8231.h" + +static void acpi_init(struct device *dev) +{ + printk_debug("Configuring VIA ACPI\n"); + + // Set ACPI base address to IO 0x4000 + pci_write_config32(dev, 0x48, 0x4001); + + // Enable ACPI access (and setup like award) + pci_write_config8(dev, 0x41, 0x84); + + // Set hardware monitor base address to IO 0x6000 + pci_write_config32(dev, 0x70, 0x6001); + + // Enable hardware monitor (and setup like award) + pci_write_config8(dev, 0x74, 0x01); + + // set IO base address to 0x5000 + pci_write_config32(dev, 0x90, 0x5001); + + // Enable SMBus + pci_write_config8(dev, 0xd2, 0x01); +} + +static struct device_operations acpi_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = acpi_init, + .enable = 0, + .ops_pci = 0, +}; + +static struct pci_driver northbridge_driver __pci_driver = { + .ops = &acpi_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8231_4, +}; diff --git a/src/southbridge/via/vt8231/vt8231_ide.c b/src/southbridge/via/vt8231/vt8231_ide.c new file mode 100644 index 0000000000..70f256990c --- /dev/null +++ b/src/southbridge/via/vt8231/vt8231_ide.c @@ -0,0 +1,108 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.h> +#include <device/pci_ids.h> +#include "vt8231.h" +#include "chip.h" + +static void ide_init(struct device *dev) +{ + struct southbridge_via_vt8231_config *conf; + unsigned char enables; + + if (!conf->enable_native_ide) { + // Run the IDE controller in 'compatiblity mode - i.e. don't use PCI + // interrupts. Using PCI ints confuses linux for some reason. + + printk_info("%s: enabling compatibility IDE addresses\n", __FUNCTION__); + enables = pci_read_config8(dev, 0x42); + printk_debug("enables in reg 0x42 0x%x\n", enables); + enables &= ~0xc0; // compatability mode + pci_write_config8(dev, 0x42, enables); + enables = pci_read_config8(dev, 0x42); + printk_debug("enables in reg 0x42 read back as 0x%x\n", enables); + } + + enables = pci_read_config8(dev, 0x40); + printk_debug("enables in reg 0x40 0x%x\n", enables); + enables |= 3; + pci_write_config8(dev, 0x40, enables); + enables = pci_read_config8(dev, 0x40); + printk_debug("enables in reg 0x40 read back as 0x%x\n", enables); + + // Enable prefetch buffers + enables = pci_read_config8(dev, 0x41); + enables |= 0xf0; + pci_write_config8(dev, 0x41, enables); + + // Lower thresholds (cause award does it) + enables = pci_read_config8(dev, 0x43); + enables &= ~0x0f; + enables |= 0x05; + pci_write_config8(dev, 0x43, enables); + + // PIO read prefetch counter (cause award does it) + pci_write_config8(dev, 0x44, 0x18); + + // Use memory read multiple + pci_write_config8(dev, 0x45, 0x1c); + + // address decoding. + // we want "flexible", i.e. 1f0-1f7 etc. or native PCI + // kevinh@ispiri.com - the standard linux drivers seem ass slow when + // used in native mode - I've changed back to classic + enables = pci_read_config8(dev, 0x9); + printk_debug("enables in reg 0x9 0x%x\n", enables); + // by the book, set the low-order nibble to 0xa. + if (conf->enable_native_ide) { + enables &= ~0xf; + // cf/cg silicon needs an 'f' here. + enables |= 0xf; + } else { + enables &= ~0x5; + } + + pci_write_config8(dev, 0x9, enables); + enables = pci_read_config8(dev, 0x9); + printk_debug("enables in reg 0x9 read back as 0x%x\n", enables); + + // standard bios sets master bit. + enables = pci_read_config8(dev, 0x4); + printk_debug("command in reg 0x4 0x%x\n", enables); + enables |= 7; + + // No need for stepping - kevinh@ispiri.com + enables &= ~0x80; + + pci_write_config8(dev, 0x4, enables); + enables = pci_read_config8(dev, 0x4); + printk_debug("command in reg 0x4 reads back as 0x%x\n", enables); + + if (!conf->enable_native_ide) { + // Use compatability mode - per award bios + pci_write_config32(dev, 0x10, 0x0); + pci_write_config32(dev, 0x14, 0x0); + pci_write_config32(dev, 0x18, 0x0); + pci_write_config32(dev, 0x1c, 0x0); + + // Force interrupts to use compat mode - just like Award bios + pci_write_config8(dev, 0x3d, 00); + pci_write_config8(dev, 0x3c, 0xff); + } +} + +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, + .enable = 0, + .ops_pci = 0, +}; + +static struct pci_driver northbridge_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_82C586_1, +}; diff --git a/src/southbridge/via/vt8231/vt8231_lpc.c b/src/southbridge/via/vt8231/vt8231_lpc.c new file mode 100644 index 0000000000..9564b55ae7 --- /dev/null +++ b/src/southbridge/via/vt8231/vt8231_lpc.c @@ -0,0 +1,154 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.h> +#include <device/pci_ids.h> + +#include <pc80/mc146818rtc.h> + +#include "vt8231.h" +#include "chip.h" + +/* PIRQ init + */ +void pci_assign_irqs(unsigned bus, unsigned slot, const unsigned char pIntAtoD[4]); +static const unsigned char southbridgeIrqs[4] = { 11, 5, 10, 12 }; +static const unsigned char enetIrqs[4] = { 11, 5, 10, 12 }; +static const unsigned char slotIrqs[4] = { 5, 10, 12, 11 }; + +/* + Our IDSEL mappings are as follows + PCI slot is AD31 (device 15) (00:14.0) + Southbridge is AD28 (device 12) (00:11.0) +*/ +static void pci_routing_fixup(struct device *dev) +{ + + printk_info("%s: dev is %p\n", __FUNCTION__, dev); + if (dev) { + /* initialize PCI interupts - these assignments depend + on the PCB routing of PINTA-D + + PINTA = IRQ11 + PINTB = IRQ5 + PINTC = IRQ10 + PINTD = IRQ12 + */ + pci_write_config8(dev, 0x55, 0xb0); + pci_write_config8(dev, 0x56, 0xa5); + pci_write_config8(dev, 0x57, 0xc0); + } + + // Standard southbridge components + printk_info("setting southbridge\n"); + pci_assign_irqs(0, 0x11, southbridgeIrqs); + + // Ethernet built into southbridge + printk_info("setting ethernet\n"); + pci_assign_irqs(0, 0x12, enetIrqs); + + // PCI slot + printk_info("setting pci slot\n"); + pci_assign_irqs(0, 0x14, slotIrqs); + printk_info("%s: DONE\n", __FUNCTION__); +} + +static void vt8231_init(struct device *dev) +{ + unsigned char enables; + struct southbridge_via_vt8231_config *conf = dev->chip_info; + + printk_debug("vt8231 init\n"); + + // enable the internal I/O decode + enables = pci_read_config8(dev, 0x6C); + enables |= 0x80; + pci_write_config8(dev, 0x6C, enables); + + // Map 4MB of FLASH into the address space + pci_write_config8(dev, 0x41, 0x7f); + + // Set bit 6 of 0x40, because Award does it (IO recovery time) + // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI + // interrupts can be properly marked as level triggered. + enables = pci_read_config8(dev, 0x40); + pci_write_config8(dev, 0x40, enables); + + // Set 0x42 to 0xf0 to match Award bios + enables = pci_read_config8(dev, 0x42); + enables |= 0xf0; + pci_write_config8(dev, 0x42, enables); + + // Set bit 3 of 0x4a, to match award (dummy pci request) + enables = pci_read_config8(dev, 0x4a); + enables |= 0x08; + pci_write_config8(dev, 0x4a, enables); + + // Set bit 3 of 0x4f to match award (use INIT# as cpu reset) + enables = pci_read_config8(dev, 0x4f); + enables |= 0x08; + pci_write_config8(dev, 0x4f, enables); + + // Set 0x58 to 0x03 to match Award + pci_write_config8(dev, 0x58, 0x03); + + // enable the ethernet/RTC + if (dev) { + enables = pci_read_config8(dev, 0x51); + enables |= 0x18; + pci_write_config8(dev, 0x51, enables); + } + + // enable IDE, since Linux won't do it. + // First do some more things to devfn (17,0) + // note: this should already be cleared, according to the book. + enables = pci_read_config8(dev, 0x50); + printk_debug("IDE enable in reg. 50 is 0x%x\n", enables); + enables &= ~8; // need manifest constant here! + printk_debug("set IDE reg. 50 to 0x%x\n", enables); + pci_write_config8(dev, 0x50, enables); + + // set default interrupt values (IDE) + enables = pci_read_config8(dev, 0x4c); + printk_debug("IRQs in reg. 4c are 0x%x\n", enables & 0xf); + // clear out whatever was there. + enables &= ~0xf; + enables |= 4; + printk_debug("setting reg. 4c to 0x%x\n", enables); + pci_write_config8(dev, 0x4c, enables); + + // set up the serial port interrupts. + // com2 to 3, com1 to 4 + pci_write_config8(dev, 0x46, 0x04); + pci_write_config8(dev, 0x47, 0x03); + pci_write_config8(dev, 0x6e, 0x98); + + /* set up isa bus -- i/o recovery time, rom write enable, extend-ale */ + pci_write_config8(dev, 0x40, 0x54); + //ethernet_fixup(); + + // Start the rtc + rtc_init(0); +} + +static void southbridge_init(struct device *dev) +{ + vt8231_init(dev); + pci_routing_fixup(dev); +} + +static struct device_operations vt8231_lpc_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = &southbridge_init, + .scan_bus = scan_static_bus, + .enable = 0, + .ops_pci = 0, +}; + +static struct pci_driver lpc_driver __pci_driver = { + .ops = &vt8231_lpc_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8231, +}; diff --git a/src/southbridge/via/vt8231/vt8231_nic.c b/src/southbridge/via/vt8231/vt8231_nic.c new file mode 100644 index 0000000000..13da26345c --- /dev/null +++ b/src/southbridge/via/vt8231/vt8231_nic.c @@ -0,0 +1,37 @@ +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ops.h> +#include <device/pci_ids.h> +#include "vt8231.h" + +/* + * Enable the ethernet device and turn off stepping (because it is integrated + * inside the southbridge) + */ +static void nic_init(struct device *dev) +{ + uint8_t byte; + + printk_debug("Configuring VIA LAN\n"); + + /* We don't need stepping - though the device supports it */ + byte = pci_read_config8(dev, PCI_COMMAND); + byte &= ~PCI_COMMAND_WAIT; + pci_write_config8(dev, PCI_COMMAND, byte); +} + +static struct device_operations nic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = nic_init, + .enable = 0, + .ops_pci = 0, +}; + +static struct pci_driver northbridge_driver __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8233_7, +}; diff --git a/src/southbridge/via/vt8231/vt8231_usb.c b/src/southbridge/via/vt8231/vt8231_usb.c new file mode 100644 index 0000000000..3dd0b4272b --- /dev/null +++ b/src/southbridge/via/vt8231/vt8231_usb.c @@ -0,0 +1,52 @@ + +static void usb_on(int enable) +{ + unsigned char regval; + + /* Base 8231 controller */ + device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0); + /* USB controller 1 */ + device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, 0); + /* USB controller 2 */ + device_t dev3 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev2); + + /* enable USB1 */ + if(dev2) { + if (enable) { + pci_write_config8(dev2, 0x3c, 0x05); + pci_write_config8(dev2, 0x04, 0x07); + } else { + pci_write_config8(dev2, 0x3c, 0x00); + pci_write_config8(dev2, 0x04, 0x00); + } + } + + if(dev0) { + regval = pci_read_config8(dev0, 0x50); + if (enable) + regval &= ~(0x10); + else + regval |= 0x10; + pci_write_config8(dev0, 0x50, regval); + } + + /* enable USB2 */ + if(dev3) { + if (enable) { + pci_write_config8(dev3, 0x3c, 0x05); + pci_write_config8(dev3, 0x04, 0x07); + } else { + pci_write_config8(dev3, 0x3c, 0x00); + pci_write_config8(dev3, 0x04, 0x00); + } + } + + if(dev0) { + regval = pci_read_config8(dev0, 0x50); + if (enable) + regval &= ~(0x20); + else + regval |= 0x20; + pci_write_config8(dev0, 0x50, regval); + } +} |