summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller/ehci_pci.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-09-28 07:06:47 +0000
committerthompsa <thompsa@FreeBSD.org>2009-09-28 07:06:47 +0000
commit1e9eba768b172293ce6122b0116174673e7b821b (patch)
tree4bd4ec1fed30a56794530227f7f3528fc97691bb /sys/dev/usb/controller/ehci_pci.c
parentd0aa741310827933f03f54a327c7943ac8bab8e1 (diff)
downloadFreeBSD-src-1e9eba768b172293ce6122b0116174673e7b821b.zip
FreeBSD-src-1e9eba768b172293ce6122b0116174673e7b821b.tar.gz
Import two PCI quirks from Linux
- Add quirk for ATI SB600 and SB700 to free SMB controller - Correct schedule sleep time to 10us on the VIA ehci controller Reported by: Dorian B<FC>ttner, Andriy Gapon Submitted by: Hans Petter Selasky
Diffstat (limited to 'sys/dev/usb/controller/ehci_pci.c')
-rw-r--r--sys/dev/usb/controller/ehci_pci.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c
index 7f8c0a0..7978f4f 100644
--- a/sys/dev/usb/controller/ehci_pci.c
+++ b/sys/dev/usb/controller/ehci_pci.c
@@ -240,6 +240,50 @@ ehci_pci_probe(device_t self)
}
}
+static void
+ehci_pci_ati_quirk(device_t self, uint8_t is_sb700)
+{
+ device_t smbdev;
+ uint32_t val;
+
+ if (is_sb700) {
+ /* Lookup SMBUS PCI device */
+ smbdev = pci_find_device(PCI_EHCI_VENDORID_ATI, 0x4385);
+ if (smbdev == NULL)
+ return;
+ val = pci_get_revid(smbdev);
+ if (val != 0x3a && val != 0x3b)
+ return;
+ }
+
+ /*
+ * Note: this bit is described as reserved in SB700
+ * Register Reference Guide.
+ */
+ val = pci_read_config(self, 0x53, 1);
+ if (!(val & 0x8)) {
+ val |= 0x8;
+ pci_write_config(self, 0x53, val, 1);
+ device_printf(self, "AMD SB600/700 quirk applied\n");
+ }
+}
+
+static void
+ehci_pci_via_quirk(device_t self)
+{
+ uint32_t val;
+
+ if ((pci_get_device(self) == 0x3104) &&
+ ((pci_get_revid(self) & 0xf0) == 0x60)) {
+ /* Correct schedule sleep time to 10us */
+ val = pci_read_config(self, 0x4b, 1);
+ if (val & 0x20)
+ return;
+ pci_write_config(self, 0x4b, val, 1);
+ device_printf(self, "VIA-quirk applied\n");
+ }
+}
+
static int
ehci_pci_attach(device_t self)
{
@@ -370,6 +414,32 @@ ehci_pci_attach(device_t self)
goto error;
}
ehci_pci_takecontroller(self);
+
+ /* Undocumented quirks taken from Linux */
+
+ switch (pci_get_vendor(self)) {
+ case PCI_EHCI_VENDORID_ATI:
+ /* SB600 and SB700 EHCI quirk */
+ switch (pci_get_device(self)) {
+ case 0x4386:
+ ehci_pci_ati_quirk(self, 0);
+ break;
+ case 0x4396:
+ ehci_pci_ati_quirk(self, 1);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case PCI_EHCI_VENDORID_VIA:
+ ehci_pci_via_quirk(self);
+ break;
+
+ default:
+ break;
+ }
+
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
OpenPOWER on IntegriCloud