diff --git a/src/southbridge/nvidia/ck804/chip.h b/src/southbridge/nvidia/ck804/chip.h index a9b18fb021..4c8d7b10bc 100644 --- a/src/southbridge/nvidia/ck804/chip.h +++ b/src/southbridge/nvidia/ck804/chip.h @@ -1,10 +1,11 @@ #ifndef CK804_CHIP_H #define CK804_CHIP_H -struct southbridge_nvidia_ck804_config +struct southbridge_nvidia_ck804_config { - unsigned int ide0_enable : 1; - unsigned int ide1_enable : 1; + unsigned int usb1_hc_reset : 1; + unsigned int ide0_enable : 1; + unsigned int ide1_enable : 1; unsigned int sata0_enable : 1; unsigned int sata1_enable : 1; unsigned long nic_rom_address; diff --git a/src/southbridge/nvidia/ck804/ck804_usb.c b/src/southbridge/nvidia/ck804/ck804_usb.c index a839b7e338..d0b686abbc 100644 --- a/src/southbridge/nvidia/ck804/ck804_usb.c +++ b/src/southbridge/nvidia/ck804/ck804_usb.c @@ -9,9 +9,22 @@ #include #include "ck804.h" +static void usb1_init(struct device *dev) { + struct southbridge_nvidia_ck804_config const * conf=dev->chip_info; + if (conf->usb1_hc_reset) { + //Somehow the warm reset does not really resets the USB controller. + //Later, during boot, when the Bus Master bit is set, the USB + //controller trashes the memory, causing weird misbehavior. + //Was detected on Sun Ultra40, where mptable was damaged. + uint32_t bar0=pci_read_config32(dev,0x10); + uint32_t* regs=(uint32_t*)(bar0&~0xfff); + regs[2]|=1; //OHCI USB HCCommandStatus Register, HostControllerReset bit + } +} + static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x40, +{ + pci_write_config32(dev, 0x40, ((device & 0xffff) << 16) | (vendor & 0xffff)); } static struct pci_operations lops_pci = { @@ -22,7 +35,7 @@ static struct device_operations usb_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = 0, + .init = usb1_init, // .enable = ck804_enable, .scan_bus = 0, .ops_pci = &lops_pci,