/* * Copyright 2004 Tyan Computer * by yhlu@tyan.com */ #include #include #include #include #include #include #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<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, };