aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r--drivers/usb/host/ohci-pci.c126
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
39static struct pci_dev *amd_smbus_dev;
40static struct pci_dev *amd_hb_dev;
41static int amd_ohci_iso_count;
42
43/*-------------------------------------------------------------------------*/ 25/*-------------------------------------------------------------------------*/
44 26
45static int broken_suspend(struct usb_hcd *hcd) 27static int broken_suspend(struct usb_hcd *hcd)
@@ -168,15 +150,18 @@ static int ohci_quirk_nec(struct usb_hcd *hcd)
168static int ohci_quirk_amd700(struct usb_hcd *hcd) 150static 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 */
218static void quirk_amd_pll(int on) 182static 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
256static 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
272static void sb800_prefetch(struct ohci_hcd *ohci, int on) 200static 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.