diff options
author | arch import user (historical) <svn@openbios.org> | 2005-07-06 17:13:46 +0000 |
---|---|---|
committer | arch import user (historical) <svn@openbios.org> | 2005-07-06 17:13:46 +0000 |
commit | 98d0d30f6b8237f888cd44b33292319e3c167a47 (patch) | |
tree | 0571a9e863b7a7749c2e4fd5bda7ec080831a73c /src/southbridge/nvidia/ck804/ck804.c | |
parent | 577f185d382c8130f20f0ee7e8466ed8bbebbacc (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.c | 197 |
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, +}; |