diff options
Diffstat (limited to 'drivers/usb/host/ehci-pci.c')
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a1e8d273103f..566791e04e8c 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -41,6 +41,42 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | |||
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci) | ||
45 | { | ||
46 | struct pci_dev *amd_smbus_dev; | ||
47 | u8 rev = 0; | ||
48 | |||
49 | amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); | ||
50 | if (amd_smbus_dev) { | ||
51 | pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); | ||
52 | if (rev < 0x40) { | ||
53 | pci_dev_put(amd_smbus_dev); | ||
54 | amd_smbus_dev = NULL; | ||
55 | return 0; | ||
56 | } | ||
57 | } else { | ||
58 | amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL); | ||
59 | if (!amd_smbus_dev) | ||
60 | return 0; | ||
61 | pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); | ||
62 | if (rev < 0x11 || rev > 0x18) { | ||
63 | pci_dev_put(amd_smbus_dev); | ||
64 | amd_smbus_dev = NULL; | ||
65 | return 0; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | if (!amd_nb_dev) | ||
70 | amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); | ||
71 | |||
72 | ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n"); | ||
73 | |||
74 | pci_dev_put(amd_smbus_dev); | ||
75 | amd_smbus_dev = NULL; | ||
76 | |||
77 | return 1; | ||
78 | } | ||
79 | |||
44 | /* called during probe() after chip reset completes */ | 80 | /* called during probe() after chip reset completes */ |
45 | static int ehci_pci_setup(struct usb_hcd *hcd) | 81 | static int ehci_pci_setup(struct usb_hcd *hcd) |
46 | { | 82 | { |
@@ -99,6 +135,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
99 | /* cache this readonly data; minimize chip reads */ | 135 | /* cache this readonly data; minimize chip reads */ |
100 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | 136 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
101 | 137 | ||
138 | if (ehci_quirk_amd_hudson(ehci)) | ||
139 | ehci->amd_l1_fix = 1; | ||
140 | |||
102 | retval = ehci_halt(ehci); | 141 | retval = ehci_halt(ehci); |
103 | if (retval) | 142 | if (retval) |
104 | return retval; | 143 | return retval; |
@@ -148,6 +187,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
148 | if (pdev->revision < 0xa4) | 187 | if (pdev->revision < 0xa4) |
149 | ehci->no_selective_suspend = 1; | 188 | ehci->no_selective_suspend = 1; |
150 | break; | 189 | break; |
190 | |||
191 | /* MCP89 chips on the MacBookAir3,1 give EPROTO when | ||
192 | * fetching device descriptors unless LPM is disabled. | ||
193 | * There are also intermittent problems enumerating | ||
194 | * devices with PPCD enabled. | ||
195 | */ | ||
196 | case 0x0d9d: | ||
197 | ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); | ||
198 | ehci->has_lpm = 0; | ||
199 | ehci->has_ppcd = 0; | ||
200 | ehci->command &= ~CMD_PPCEE; | ||
201 | break; | ||
151 | } | 202 | } |
152 | break; | 203 | break; |
153 | case PCI_VENDOR_ID_VIA: | 204 | case PCI_VENDOR_ID_VIA: |
@@ -296,8 +347,8 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) | |||
296 | * mark HW unaccessible. The PM and USB cores make sure that | 347 | * mark HW unaccessible. The PM and USB cores make sure that |
297 | * the root hub is either suspended or stopped. | 348 | * the root hub is either suspended or stopped. |
298 | */ | 349 | */ |
299 | spin_lock_irqsave (&ehci->lock, flags); | ||
300 | ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); | 350 | ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); |
351 | spin_lock_irqsave (&ehci->lock, flags); | ||
301 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 352 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
302 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); | 353 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); |
303 | 354 | ||