aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-pci.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-02-17 12:54:16 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-17 12:54:16 -0500
commit479b46b5599b1e610630d7332e168c1f9c4ee0b4 (patch)
treec5d7e48576f5b5b6a61a2a2e5f85abaa941b85ab /drivers/usb/host/ohci-pci.c
parentce1fd3585709e833ad102167024e97217734dbfd (diff)
Revert "USB host: Move AMD PLL quirk to pci-quirks.c"
This reverts commit b7d5b439b7a40dd0a0202fe1c118615a3fcc3b25. It conflicts with commit baab93afc2844b68d57b0dcca5e1d34c5d7cf411 "USB: EHCI: ASPM quirk of ISOC on AMD Hudson" and merging the two just doesn't work properly. Cc: Andiry Xu <andiry.xu@amd.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Alex He <alex.he@amd.com> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r--drivers/usb/host/ohci-pci.c110
1 files changed, 102 insertions, 8 deletions
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 9816a2870d00..36ee9a666e93 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -22,6 +22,24 @@
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
25/*-------------------------------------------------------------------------*/ 43/*-------------------------------------------------------------------------*/
26 44
27static int broken_suspend(struct usb_hcd *hcd) 45static int broken_suspend(struct usb_hcd *hcd)
@@ -150,14 +168,11 @@ static int ohci_quirk_nec(struct usb_hcd *hcd)
150static int ohci_quirk_amd700(struct usb_hcd *hcd) 168static int ohci_quirk_amd700(struct usb_hcd *hcd)
151{ 169{
152 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 170 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
153 struct pci_dev *amd_smbus_dev;
154 u8 rev = 0; 171 u8 rev = 0;
155 172
156 if (usb_amd_find_chipset_info()) 173 if (!amd_smbus_dev)
157 ohci->flags |= OHCI_QUIRK_AMD_PLL; 174 amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
158 175 PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
159 amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
160 PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
161 if (!amd_smbus_dev) 176 if (!amd_smbus_dev)
162 return 0; 177 return 0;
163 178
@@ -169,8 +184,19 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
169 ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); 184 ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
170 } 185 }
171 186
172 pci_dev_put(amd_smbus_dev); 187 if ((rev > 0x3b) || (rev < 0x30)) {
173 amd_smbus_dev = NULL; 188 pci_dev_put(amd_smbus_dev);
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");
174 200
175 return 0; 201 return 0;
176} 202}
@@ -189,6 +215,74 @@ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
189 return 0; 215 return 0;
190} 216}
191 217
218/*
219 * The hardware normally enables the A-link power management feature, which
220 * lets the system lower the power consumption in idle states.
221 *
222 * Assume the system is configured to have USB 1.1 ISO transfers going
223 * to or from a USB device. Without this quirk, that stream may stutter
224 * or have breaks occasionally. For transfers going to speakers, this
225 * makes a very audible mess...
226 *
227 * That audio playback corruption is due to the audio stream getting
228 * interrupted occasionally when the link goes in lower power state
229 * This USB quirk prevents the link going into that lower power state
230 * during audio playback or other ISO operations.
231 */
232static void quirk_amd_pll(int on)
233{
234 u32 addr;
235 u32 val;
236 u32 bit = (on > 0) ? 1 : 0;
237
238 pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr);
239
240 /* BIT names/meanings are NDA-protected, sorry ... */
241
242 outl(AX_INDXC, AB_INDX(addr));
243 outl(0x40, AB_DATA(addr));
244 outl(AX_DATAC, AB_INDX(addr));
245 val = inl(AB_DATA(addr));
246 val &= ~((1 << 3) | (1 << 4) | (1 << 9));
247 val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9);
248 outl(val, AB_DATA(addr));
249
250 if (amd_hb_dev) {
251 addr = PCIE_P_CNTL;
252 pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
253
254 pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
255 val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
256 val |= bit | (bit << 3) | (bit << 12);
257 val |= ((!bit) << 4) | ((!bit) << 9);
258 pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
259
260 addr = BIF_NB;
261 pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
262
263 pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
264 val &= ~(1 << 8);
265 val |= bit << 8;
266 pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
267 }
268}
269
270static void amd_iso_dev_put(void)
271{
272 amd_ohci_iso_count--;
273 if (amd_ohci_iso_count == 0) {
274 if (amd_smbus_dev) {
275 pci_dev_put(amd_smbus_dev);
276 amd_smbus_dev = NULL;
277 }
278 if (amd_hb_dev) {
279 pci_dev_put(amd_hb_dev);
280 amd_hb_dev = NULL;
281 }
282 }
283
284}
285
192static void sb800_prefetch(struct ohci_hcd *ohci, int on) 286static void sb800_prefetch(struct ohci_hcd *ohci, int on)
193{ 287{
194 struct pci_dev *pdev; 288 struct pci_dev *pdev;