diff options
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 126 |
1 files changed, 29 insertions, 97 deletions
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 6bdc8b25a6a1..ad8166c681e2 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -22,24 +22,6 @@ | |||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | 24 | ||
25 | /* constants used to work around PM-related transfer | ||
26 | * glitches in some AMD 700 series southbridges | ||
27 | */ | ||
28 | #define AB_REG_BAR 0xf0 | ||
29 | #define AB_INDX(addr) ((addr) + 0x00) | ||
30 | #define AB_DATA(addr) ((addr) + 0x04) | ||
31 | #define AX_INDXC 0X30 | ||
32 | #define AX_DATAC 0x34 | ||
33 | |||
34 | #define NB_PCIE_INDX_ADDR 0xe0 | ||
35 | #define NB_PCIE_INDX_DATA 0xe4 | ||
36 | #define PCIE_P_CNTL 0x10040 | ||
37 | #define BIF_NB 0x10002 | ||
38 | |||
39 | static struct pci_dev *amd_smbus_dev; | ||
40 | static struct pci_dev *amd_hb_dev; | ||
41 | static int amd_ohci_iso_count; | ||
42 | |||
43 | /*-------------------------------------------------------------------------*/ | 25 | /*-------------------------------------------------------------------------*/ |
44 | 26 | ||
45 | static int broken_suspend(struct usb_hcd *hcd) | 27 | static int broken_suspend(struct usb_hcd *hcd) |
@@ -168,15 +150,18 @@ static int ohci_quirk_nec(struct usb_hcd *hcd) | |||
168 | static int ohci_quirk_amd700(struct usb_hcd *hcd) | 150 | static int ohci_quirk_amd700(struct usb_hcd *hcd) |
169 | { | 151 | { |
170 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 152 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
171 | u8 rev = 0; | 153 | struct pci_dev *amd_smbus_dev; |
154 | u8 rev; | ||
172 | 155 | ||
173 | if (!amd_smbus_dev) | 156 | if (usb_amd_find_chipset_info()) |
174 | amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, | 157 | ohci->flags |= OHCI_QUIRK_AMD_PLL; |
175 | PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); | 158 | |
159 | amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, | ||
160 | PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); | ||
176 | if (!amd_smbus_dev) | 161 | if (!amd_smbus_dev) |
177 | return 0; | 162 | return 0; |
178 | 163 | ||
179 | pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); | 164 | rev = amd_smbus_dev->revision; |
180 | 165 | ||
181 | /* SB800 needs pre-fetch fix */ | 166 | /* SB800 needs pre-fetch fix */ |
182 | if ((rev >= 0x40) && (rev <= 0x4f)) { | 167 | if ((rev >= 0x40) && (rev <= 0x4f)) { |
@@ -184,89 +169,32 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) | |||
184 | ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); | 169 | ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); |
185 | } | 170 | } |
186 | 171 | ||
187 | if ((rev > 0x3b) || (rev < 0x30)) { | 172 | pci_dev_put(amd_smbus_dev); |
188 | pci_dev_put(amd_smbus_dev); | 173 | amd_smbus_dev = NULL; |
189 | amd_smbus_dev = NULL; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | amd_ohci_iso_count++; | ||
194 | |||
195 | if (!amd_hb_dev) | ||
196 | amd_hb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9600, NULL); | ||
197 | |||
198 | ohci->flags |= OHCI_QUIRK_AMD_ISO; | ||
199 | ohci_dbg(ohci, "enabled AMD ISO transfers quirk\n"); | ||
200 | 174 | ||
201 | return 0; | 175 | return 0; |
202 | } | 176 | } |
203 | 177 | ||
204 | /* | 178 | /* nVidia controllers continue to drive Reset signalling on the bus |
205 | * The hardware normally enables the A-link power management feature, which | 179 | * even after system shutdown, wasting power. This flag tells the |
206 | * lets the system lower the power consumption in idle states. | 180 | * shutdown routine to leave the controller OPERATIONAL instead of RESET. |
207 | * | ||
208 | * Assume the system is configured to have USB 1.1 ISO transfers going | ||
209 | * to or from a USB device. Without this quirk, that stream may stutter | ||
210 | * or have breaks occasionally. For transfers going to speakers, this | ||
211 | * makes a very audible mess... | ||
212 | * | ||
213 | * That audio playback corruption is due to the audio stream getting | ||
214 | * interrupted occasionally when the link goes in lower power state | ||
215 | * This USB quirk prevents the link going into that lower power state | ||
216 | * during audio playback or other ISO operations. | ||
217 | */ | 181 | */ |
218 | static void quirk_amd_pll(int on) | 182 | static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd) |
219 | { | 183 | { |
220 | u32 addr; | 184 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
221 | u32 val; | 185 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
222 | u32 bit = (on > 0) ? 1 : 0; | ||
223 | |||
224 | pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr); | ||
225 | |||
226 | /* BIT names/meanings are NDA-protected, sorry ... */ | ||
227 | |||
228 | outl(AX_INDXC, AB_INDX(addr)); | ||
229 | outl(0x40, AB_DATA(addr)); | ||
230 | outl(AX_DATAC, AB_INDX(addr)); | ||
231 | val = inl(AB_DATA(addr)); | ||
232 | val &= ~((1 << 3) | (1 << 4) | (1 << 9)); | ||
233 | val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9); | ||
234 | outl(val, AB_DATA(addr)); | ||
235 | |||
236 | if (amd_hb_dev) { | ||
237 | addr = PCIE_P_CNTL; | ||
238 | pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr); | ||
239 | |||
240 | pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val); | ||
241 | val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12)); | ||
242 | val |= bit | (bit << 3) | (bit << 12); | ||
243 | val |= ((!bit) << 4) | ((!bit) << 9); | ||
244 | pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val); | ||
245 | |||
246 | addr = BIF_NB; | ||
247 | pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr); | ||
248 | |||
249 | pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val); | ||
250 | val &= ~(1 << 8); | ||
251 | val |= bit << 8; | ||
252 | pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val); | ||
253 | } | ||
254 | } | ||
255 | 186 | ||
256 | static void amd_iso_dev_put(void) | 187 | /* Evidently nVidia fixed their later hardware; this is a guess at |
257 | { | 188 | * the changeover point. |
258 | amd_ohci_iso_count--; | 189 | */ |
259 | if (amd_ohci_iso_count == 0) { | 190 | #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB 0x026d |
260 | if (amd_smbus_dev) { | 191 | |
261 | pci_dev_put(amd_smbus_dev); | 192 | if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) { |
262 | amd_smbus_dev = NULL; | 193 | ohci->flags |= OHCI_QUIRK_SHUTDOWN; |
263 | } | 194 | ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); |
264 | if (amd_hb_dev) { | ||
265 | pci_dev_put(amd_hb_dev); | ||
266 | amd_hb_dev = NULL; | ||
267 | } | ||
268 | } | 195 | } |
269 | 196 | ||
197 | return 0; | ||
270 | } | 198 | } |
271 | 199 | ||
272 | static void sb800_prefetch(struct ohci_hcd *ohci, int on) | 200 | static void sb800_prefetch(struct ohci_hcd *ohci, int on) |
@@ -332,6 +260,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { | |||
332 | PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), | 260 | PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), |
333 | .driver_data = (unsigned long)ohci_quirk_amd700, | 261 | .driver_data = (unsigned long)ohci_quirk_amd700, |
334 | }, | 262 | }, |
263 | { | ||
264 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), | ||
265 | .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown, | ||
266 | }, | ||
335 | 267 | ||
336 | /* FIXME for some of the early AMD 760 southbridges, OHCI | 268 | /* FIXME for some of the early AMD 760 southbridges, OHCI |
337 | * won't work at all. blacklist them. | 269 | * won't work at all. blacklist them. |