summaryrefslogtreecommitdiff
path: root/src/southbridge/nvidia/ck804/ck804.c
diff options
context:
space:
mode:
authorarch import user (historical) <svn@openbios.org>2005-07-06 17:13:46 +0000
committerarch import user (historical) <svn@openbios.org>2005-07-06 17:13:46 +0000
commit98d0d30f6b8237f888cd44b33292319e3c167a47 (patch)
tree0571a9e863b7a7749c2e4fd5bda7ec080831a73c /src/southbridge/nvidia/ck804/ck804.c
parent577f185d382c8130f20f0ee7e8466ed8bbebbacc (diff)
Revision: linuxbios@linuxbios.org--devel/freebios--devel--2.0--patch-30
Creator: Yinghai Lu <yhlu@tyan.com> Nvidia Ck804 support git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1946 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge/nvidia/ck804/ck804.c')
-rw-r--r--src/southbridge/nvidia/ck804/ck804.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/src/southbridge/nvidia/ck804/ck804.c b/src/southbridge/nvidia/ck804/ck804.c
new file mode 100644
index 0000000000..a4b77c3596
--- /dev/null
+++ b/src/southbridge/nvidia/ck804/ck804.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ */
+
+#include <console/console.h>
+
+#include <arch/io.h>
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "ck804.h"
+
+static uint32_t final_reg;
+
+static device_t find_lpc_dev( device_t dev, unsigned devfn)
+{
+
+ device_t lpc_dev;
+
+ lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
+
+ if ( !lpc_dev ) return lpc_dev;
+
+ if ((lpc_dev->vendor != PCI_VENDOR_ID_NVIDIA) || (
+ (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_LPC) &&
+ (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_PRO) &&
+ (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_SLAVE)) ) {
+ uint32_t id;
+ id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
+ if ( (id != (PCI_VENDOR_ID_NVIDIA | (PCI_DEVICE_ID_NVIDIA_CK804_LPC << 16))) &&
+ (id != (PCI_VENDOR_ID_NVIDIA | (PCI_DEVICE_ID_NVIDIA_CK804_PRO << 16))) &&
+ (id != (PCI_VENDOR_ID_NVIDIA | (PCI_DEVICE_ID_NVIDIA_CK804_SLAVE << 16)))
+ ) {
+ lpc_dev = 0;
+ }
+ }
+
+ return lpc_dev;
+}
+
+void ck804_enable(device_t dev)
+{
+ device_t lpc_dev;
+ unsigned index = 0;
+ unsigned index2 = 0;
+ uint32_t reg_old, reg;
+ uint8_t byte;
+ unsigned deviceid;
+ unsigned vendorid;
+
+ struct southbridge_nvidia_ck804_config *conf;
+ conf = dev->chip_info;
+
+ unsigned devfn;
+
+ if(dev->device==0x0000) {
+ vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
+ deviceid = (vendorid>>16) & 0xffff;
+// vendorid &= 0xffff;
+ } else {
+// vendorid = dev->vendor;
+ deviceid = dev->device;
+ }
+
+ devfn = (dev->path.u.pci.devfn) & ~7;
+ switch(deviceid) {
+ case PCI_DEVICE_ID_NVIDIA_CK804_SM:
+ index = 16;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_USB:
+ devfn -= (1<<3);
+ index = 8;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_USB2:
+ devfn -= (1<<3);
+ index = 20;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_NIC:
+ devfn -= (9<<3);
+ index = 10;
+ dev->rom_address = conf->nic_rom_address;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_NIC_BRIDGE:
+ devfn -= (9<<3);
+ index = 10;
+ dev->rom_address = conf->nic_rom_address;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_ACI:
+ devfn -= (3<<3);
+ index = 12;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_MCI:
+ devfn -= (3<<3);
+ index = 13;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_IDE:
+ devfn -= (5<<3);
+ index = 14;
+ dev->rom_address = conf->raid_rom_address;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_SATA0:
+ devfn -= (6<<3);
+ index = 22;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_SATA1:
+ devfn -= (7<<3);
+ index = 18;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_PCI:
+ devfn -= (8<<3);
+ index = 15;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_CK804_PCI_E:
+ devfn -= (0xa<<3);
+ index2 = 19;
+ break;
+ default:
+ index = 0;
+ }
+
+ if(index2!=0) {
+ int i;
+ for(i=0;i<4;i++) {
+ lpc_dev = find_lpc_dev(dev, devfn - (i<<3));
+ if(!lpc_dev) continue;
+ index2 -= i;
+ break;
+ }
+
+ if ( lpc_dev ) {
+ reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
+
+ if (!dev->enabled) {
+ reg |= (1<<index2);
+ }
+
+ if (reg != reg_old) {
+ pci_write_config32(lpc_dev, 0xe4, reg);
+ }
+ }
+
+ index2 = 0;
+ return;
+ }
+
+
+ lpc_dev = find_lpc_dev(dev, devfn);
+
+ if ( !lpc_dev ) return;
+
+ if ( index == 0) {
+
+ final_reg = pci_read_config32(lpc_dev, 0xe8);
+ final_reg &= ~((1<<16)|(1<<8)|(1<<20)|(1<<10)|(1<<12)|(1<<13)|(1<<14)|(1<<22)|(1<<18)|(1<<15));
+ pci_write_config32(lpc_dev, 0xe8, final_reg);
+
+#if 1
+ reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
+ reg |= (1<<20);
+ if (reg != reg_old) {
+ pci_write_config32(lpc_dev, 0xe4, reg);
+ }
+#endif
+
+ byte = pci_read_config8(lpc_dev, 0x74);
+ byte |= ((1<<1));
+ pci_write_config8(dev, 0x74, byte);
+
+ byte = pci_read_config8(lpc_dev, 0xdd);
+ byte |= ((1<<0)|(1<<3));
+ pci_write_config8(dev, 0xdd, byte);
+
+ return;
+
+ }
+
+ if (!dev->enabled) {
+ final_reg |= (1 << index);
+ }
+
+ if(index == 10 ) {
+ reg_old = pci_read_config32(lpc_dev, 0xe8);
+ if (final_reg != reg_old) {
+ pci_write_config32(lpc_dev, 0xe8, final_reg);
+ }
+
+ }
+
+}
+
+struct chip_operations southbridge_nvidia_ck804_ops = {
+ CHIP_NAME("Nvidia ck804")
+ .enable_dev = ck804_enable,
+};