From 958a1f308a272cb0fcb0e280e2815893a86df457 Mon Sep 17 00:00:00 2001 From: Roman Kononov Date: Fri, 2 Feb 2007 22:40:10 +0000 Subject: I have Sun Ultra40 workstation. Southbridge is nVidia CrushK8-04/nforce 2200 (too many names, sounds like a criminal). 1) Linuxbios loads kernel A; kernel A loads kernel B. Everything works fine. 2) Then I push the reset button. 3) Linuxbios loads kernel A; kernel A loads kernel B. Kernel B complains about wrong checksum of the mptable and crushes later. An investigation showed that in 3), short after kernel A (v2.6.19.2) sets the Bus Master Enable bit of the nVidia's USB1 controller (pci_set_master()), the mptable gets two bytes at physical address 0x80 damaged. Nothing is plugged to the USB ports. Other two Sun workstations had the same behavior. This does not make sense to me unless the controller has a HW bug. I believe, this should better be fixed in the kernel USB driver. For now this patch offers a possibility for linuxbios to reset the USB controller by setting HostControllerReset bit in HcCommandStatus Register. It is enablead by using 'register "usb1_hc_reset"="1"' in 'chip southbridge/nvidia/ck804' section of the mainboard's Config.lb. Signed-off-by: Roman Kononov Acked-by: Ronald G. Minnich #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, -- cgit v1.2.3