aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ehci-hcd.c10
-rw-r--r--drivers/usb/host/ehci-pci.c38
-rw-r--r--drivers/usb/host/ehci-sched.c73
-rw-r--r--drivers/usb/host/ehci.h2
-rw-r--r--drivers/usb/host/ohci-hcd.c13
-rw-r--r--drivers/usb/host/ohci-pci.c110
-rw-r--r--drivers/usb/host/ohci-q.c4
-rw-r--r--drivers/usb/host/ohci.h4
-rw-r--r--drivers/usb/host/pci-quirks.c260
-rw-r--r--drivers/usb/host/pci-quirks.h19
10 files changed, 222 insertions, 311 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 30515d362c4b..6fee3cd58efe 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -114,11 +114,13 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
114 114
115#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) 115#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
116 116
117/* for ASPM quirk of ISOC on AMD SB800 */
118static struct pci_dev *amd_nb_dev;
119
117/*-------------------------------------------------------------------------*/ 120/*-------------------------------------------------------------------------*/
118 121
119#include "ehci.h" 122#include "ehci.h"
120#include "ehci-dbg.c" 123#include "ehci-dbg.c"
121#include "pci-quirks.h"
122 124
123/*-------------------------------------------------------------------------*/ 125/*-------------------------------------------------------------------------*/
124 126
@@ -530,8 +532,10 @@ static void ehci_stop (struct usb_hcd *hcd)
530 spin_unlock_irq (&ehci->lock); 532 spin_unlock_irq (&ehci->lock);
531 ehci_mem_cleanup (ehci); 533 ehci_mem_cleanup (ehci);
532 534
533 if (ehci->amd_pll_fix == 1) 535 if (amd_nb_dev) {
534 usb_amd_dev_put(); 536 pci_dev_put(amd_nb_dev);
537 amd_nb_dev = NULL;
538 }
535 539
536#ifdef EHCI_STATS 540#ifdef EHCI_STATS
537 ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", 541 ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 1ec8060e8cc4..76179c39c0e3 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -44,6 +44,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
44 return 0; 44 return 0;
45} 45}
46 46
47static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci)
48{
49 struct pci_dev *amd_smbus_dev;
50 u8 rev = 0;
51
52 amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
53 if (!amd_smbus_dev)
54 return 0;
55
56 pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
57 if (rev < 0x40) {
58 pci_dev_put(amd_smbus_dev);
59 amd_smbus_dev = NULL;
60 return 0;
61 }
62
63 if (!amd_nb_dev)
64 amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
65 if (!amd_nb_dev)
66 ehci_err(ehci, "QUIRK: unable to get AMD NB device\n");
67
68 ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n");
69
70 pci_dev_put(amd_smbus_dev);
71 amd_smbus_dev = NULL;
72
73 return 1;
74}
75
47/* called during probe() after chip reset completes */ 76/* called during probe() after chip reset completes */
48static int ehci_pci_setup(struct usb_hcd *hcd) 77static int ehci_pci_setup(struct usb_hcd *hcd)
49{ 78{
@@ -102,6 +131,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
102 /* cache this readonly data; minimize chip reads */ 131 /* cache this readonly data; minimize chip reads */
103 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 132 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
104 133
134 if (ehci_quirk_amd_SB800(ehci))
135 ehci->amd_l1_fix = 1;
136
105 retval = ehci_halt(ehci); 137 retval = ehci_halt(ehci);
106 if (retval) 138 if (retval)
107 return retval; 139 return retval;
@@ -152,9 +184,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
152 } 184 }
153 break; 185 break;
154 case PCI_VENDOR_ID_AMD: 186 case PCI_VENDOR_ID_AMD:
155 /* AMD PLL quirk */
156 if (usb_amd_find_chipset_info())
157 ehci->amd_pll_fix = 1;
158 /* AMD8111 EHCI doesn't work, according to AMD errata */ 187 /* AMD8111 EHCI doesn't work, according to AMD errata */
159 if (pdev->device == 0x7463) { 188 if (pdev->device == 0x7463) {
160 ehci_info(ehci, "ignoring AMD8111 (errata)\n"); 189 ehci_info(ehci, "ignoring AMD8111 (errata)\n");
@@ -200,9 +229,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
200 } 229 }
201 break; 230 break;
202 case PCI_VENDOR_ID_ATI: 231 case PCI_VENDOR_ID_ATI:
203 /* AMD PLL quirk */
204 if (usb_amd_find_chipset_info())
205 ehci->amd_pll_fix = 1;
206 /* SB600 and old version of SB700 have a bug in EHCI controller, 232 /* SB600 and old version of SB700 have a bug in EHCI controller,
207 * which causes usb devices lose response in some cases. 233 * which causes usb devices lose response in some cases.
208 */ 234 */
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 1543c838b3d1..30fbdbe1cf1e 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1587,6 +1587,63 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
1587 *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); 1587 *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
1588} 1588}
1589 1589
1590#define AB_REG_BAR_LOW 0xe0
1591#define AB_REG_BAR_HIGH 0xe1
1592#define AB_INDX(addr) ((addr) + 0x00)
1593#define AB_DATA(addr) ((addr) + 0x04)
1594#define NB_PCIE_INDX_ADDR 0xe0
1595#define NB_PCIE_INDX_DATA 0xe4
1596#define NB_PIF0_PWRDOWN_0 0x01100012
1597#define NB_PIF0_PWRDOWN_1 0x01100013
1598
1599static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
1600{
1601 u32 addr, addr_low, addr_high, val;
1602
1603 outb_p(AB_REG_BAR_LOW, 0xcd6);
1604 addr_low = inb_p(0xcd7);
1605 outb_p(AB_REG_BAR_HIGH, 0xcd6);
1606 addr_high = inb_p(0xcd7);
1607 addr = addr_high << 8 | addr_low;
1608 outl_p(0x30, AB_INDX(addr));
1609 outl_p(0x40, AB_DATA(addr));
1610 outl_p(0x34, AB_INDX(addr));
1611 val = inl_p(AB_DATA(addr));
1612
1613 if (disable) {
1614 val &= ~0x8;
1615 val |= (1 << 4) | (1 << 9);
1616 } else {
1617 val |= 0x8;
1618 val &= ~((1 << 4) | (1 << 9));
1619 }
1620 outl_p(val, AB_DATA(addr));
1621
1622 if (amd_nb_dev) {
1623 addr = NB_PIF0_PWRDOWN_0;
1624 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
1625 pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
1626 if (disable)
1627 val &= ~(0x3f << 7);
1628 else
1629 val |= 0x3f << 7;
1630
1631 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
1632
1633 addr = NB_PIF0_PWRDOWN_1;
1634 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
1635 pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
1636 if (disable)
1637 val &= ~(0x3f << 7);
1638 else
1639 val |= 0x3f << 7;
1640
1641 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
1642 }
1643
1644 return;
1645}
1646
1590/* fit urb's itds into the selected schedule slot; activate as needed */ 1647/* fit urb's itds into the selected schedule slot; activate as needed */
1591static int 1648static int
1592itd_link_urb ( 1649itd_link_urb (
@@ -1615,8 +1672,8 @@ itd_link_urb (
1615 } 1672 }
1616 1673
1617 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 1674 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
1618 if (ehci->amd_pll_fix == 1) 1675 if (ehci->amd_l1_fix == 1)
1619 usb_amd_quirk_pll_disable(); 1676 ehci_quirk_amd_L1(ehci, 1);
1620 } 1677 }
1621 1678
1622 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; 1679 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1744,8 +1801,8 @@ itd_complete (
1744 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 1801 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
1745 1802
1746 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 1803 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
1747 if (ehci->amd_pll_fix == 1) 1804 if (ehci->amd_l1_fix == 1)
1748 usb_amd_quirk_pll_enable(); 1805 ehci_quirk_amd_L1(ehci, 0);
1749 } 1806 }
1750 1807
1751 if (unlikely(list_is_singular(&stream->td_list))) { 1808 if (unlikely(list_is_singular(&stream->td_list))) {
@@ -2035,8 +2092,8 @@ sitd_link_urb (
2035 } 2092 }
2036 2093
2037 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 2094 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
2038 if (ehci->amd_pll_fix == 1) 2095 if (ehci->amd_l1_fix == 1)
2039 usb_amd_quirk_pll_disable(); 2096 ehci_quirk_amd_L1(ehci, 1);
2040 } 2097 }
2041 2098
2042 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; 2099 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -2140,8 +2197,8 @@ sitd_complete (
2140 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 2197 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
2141 2198
2142 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 2199 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
2143 if (ehci->amd_pll_fix == 1) 2200 if (ehci->amd_l1_fix == 1)
2144 usb_amd_quirk_pll_enable(); 2201 ehci_quirk_amd_L1(ehci, 0);
2145 } 2202 }
2146 2203
2147 if (list_is_singular(&stream->td_list)) { 2204 if (list_is_singular(&stream->td_list)) {
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index f86d3fa20214..799ac16a54b4 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -131,7 +131,7 @@ struct ehci_hcd { /* one per controller */
131 unsigned has_amcc_usb23:1; 131 unsigned has_amcc_usb23:1;
132 unsigned need_io_watchdog:1; 132 unsigned need_io_watchdog:1;
133 unsigned broken_periodic:1; 133 unsigned broken_periodic:1;
134 unsigned amd_pll_fix:1; 134 unsigned amd_l1_fix:1;
135 unsigned fs_i_thresh:1; /* Intel iso scheduling */ 135 unsigned fs_i_thresh:1; /* Intel iso scheduling */
136 unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ 136 unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/
137 137
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 7b791bf1e7b4..759a12ff8048 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,7 +75,6 @@ static const char hcd_name [] = "ohci_hcd";
75#define STATECHANGE_DELAY msecs_to_jiffies(300) 75#define STATECHANGE_DELAY msecs_to_jiffies(300)
76 76
77#include "ohci.h" 77#include "ohci.h"
78#include "pci-quirks.h"
79 78
80static void ohci_dump (struct ohci_hcd *ohci, int verbose); 79static void ohci_dump (struct ohci_hcd *ohci, int verbose);
81static int ohci_init (struct ohci_hcd *ohci); 80static int ohci_init (struct ohci_hcd *ohci);
@@ -86,8 +85,18 @@ static int ohci_restart (struct ohci_hcd *ohci);
86#endif 85#endif
87 86
88#ifdef CONFIG_PCI 87#ifdef CONFIG_PCI
88static void quirk_amd_pll(int state);
89static void amd_iso_dev_put(void);
89static void sb800_prefetch(struct ohci_hcd *ohci, int on); 90static void sb800_prefetch(struct ohci_hcd *ohci, int on);
90#else 91#else
92static inline void quirk_amd_pll(int state)
93{
94 return;
95}
96static inline void amd_iso_dev_put(void)
97{
98 return;
99}
91static inline void sb800_prefetch(struct ohci_hcd *ohci, int on) 100static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
92{ 101{
93 return; 102 return;
@@ -903,7 +912,7 @@ static void ohci_stop (struct usb_hcd *hcd)
903 if (quirk_zfmicro(ohci)) 912 if (quirk_zfmicro(ohci))
904 del_timer(&ohci->unlink_watchdog); 913 del_timer(&ohci->unlink_watchdog);
905 if (quirk_amdiso(ohci)) 914 if (quirk_amdiso(ohci))
906 usb_amd_dev_put(); 915 amd_iso_dev_put();
907 916
908 remove_debug_files (ohci); 917 remove_debug_files (ohci);
909 ohci_mem_cleanup (ohci); 918 ohci_mem_cleanup (ohci);
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;
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index dd24fc115e48..83094d067e0f 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -52,7 +52,7 @@ __acquires(ohci->lock)
52 ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--; 52 ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
53 if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) { 53 if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
54 if (quirk_amdiso(ohci)) 54 if (quirk_amdiso(ohci))
55 usb_amd_quirk_pll_enable(); 55 quirk_amd_pll(1);
56 if (quirk_amdprefetch(ohci)) 56 if (quirk_amdprefetch(ohci))
57 sb800_prefetch(ohci, 0); 57 sb800_prefetch(ohci, 0);
58 } 58 }
@@ -686,7 +686,7 @@ static void td_submit_urb (
686 } 686 }
687 if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) { 687 if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
688 if (quirk_amdiso(ohci)) 688 if (quirk_amdiso(ohci))
689 usb_amd_quirk_pll_disable(); 689 quirk_amd_pll(0);
690 if (quirk_amdprefetch(ohci)) 690 if (quirk_amdprefetch(ohci))
691 sb800_prefetch(ohci, 1); 691 sb800_prefetch(ohci, 1);
692 } 692 }
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index bad11a72c202..51facb985c84 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -401,7 +401,7 @@ struct ohci_hcd {
401#define OHCI_QUIRK_NEC 0x40 /* lost interrupts */ 401#define OHCI_QUIRK_NEC 0x40 /* lost interrupts */
402#define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */ 402#define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */
403#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ 403#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
404#define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ 404#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
405#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ 405#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
406#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */ 406#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */
407 // there are also chip quirks/bugs in init logic 407 // there are also chip quirks/bugs in init logic
@@ -433,7 +433,7 @@ static inline int quirk_zfmicro(struct ohci_hcd *ohci)
433} 433}
434static inline int quirk_amdiso(struct ohci_hcd *ohci) 434static inline int quirk_amdiso(struct ohci_hcd *ohci)
435{ 435{
436 return ohci->flags & OHCI_QUIRK_AMD_PLL; 436 return ohci->flags & OHCI_QUIRK_AMD_ISO;
437} 437}
438static inline int quirk_amdprefetch(struct ohci_hcd *ohci) 438static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
439{ 439{
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 344b25a790e1..4c502c890ebd 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -52,266 +52,6 @@
52#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ 52#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
53#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ 53#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
54 54
55/* AMD quirk use */
56#define AB_REG_BAR_LOW 0xe0
57#define AB_REG_BAR_HIGH 0xe1
58#define AB_REG_BAR_SB700 0xf0
59#define AB_INDX(addr) ((addr) + 0x00)
60#define AB_DATA(addr) ((addr) + 0x04)
61#define AX_INDXC 0x30
62#define AX_DATAC 0x34
63
64#define NB_PCIE_INDX_ADDR 0xe0
65#define NB_PCIE_INDX_DATA 0xe4
66#define PCIE_P_CNTL 0x10040
67#define BIF_NB 0x10002
68#define NB_PIF0_PWRDOWN_0 0x01100012
69#define NB_PIF0_PWRDOWN_1 0x01100013
70
71static struct amd_chipset_info {
72 struct pci_dev *nb_dev;
73 struct pci_dev *smbus_dev;
74 int nb_type;
75 int sb_type;
76 int isoc_reqs;
77 int probe_count;
78 int probe_result;
79} amd_chipset;
80
81static DEFINE_SPINLOCK(amd_lock);
82
83int usb_amd_find_chipset_info(void)
84{
85 u8 rev = 0;
86 unsigned long flags;
87
88 spin_lock_irqsave(&amd_lock, flags);
89
90 amd_chipset.probe_count++;
91 /* probe only once */
92 if (amd_chipset.probe_count > 1) {
93 spin_unlock_irqrestore(&amd_lock, flags);
94 return amd_chipset.probe_result;
95 }
96
97 amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
98 if (amd_chipset.smbus_dev) {
99 pci_read_config_byte(amd_chipset.smbus_dev,
100 PCI_REVISION_ID, &rev);
101 if (rev >= 0x40)
102 amd_chipset.sb_type = 1;
103 else if (rev >= 0x30 && rev <= 0x3b)
104 amd_chipset.sb_type = 3;
105 } else {
106 amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
107 0x780b, NULL);
108 if (!amd_chipset.smbus_dev) {
109 spin_unlock_irqrestore(&amd_lock, flags);
110 return 0;
111 }
112 pci_read_config_byte(amd_chipset.smbus_dev,
113 PCI_REVISION_ID, &rev);
114 if (rev >= 0x11 && rev <= 0x18)
115 amd_chipset.sb_type = 2;
116 }
117
118 if (amd_chipset.sb_type == 0) {
119 if (amd_chipset.smbus_dev) {
120 pci_dev_put(amd_chipset.smbus_dev);
121 amd_chipset.smbus_dev = NULL;
122 }
123 spin_unlock_irqrestore(&amd_lock, flags);
124 return 0;
125 }
126
127 amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL);
128 if (amd_chipset.nb_dev) {
129 amd_chipset.nb_type = 1;
130 } else {
131 amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
132 0x1510, NULL);
133 if (amd_chipset.nb_dev) {
134 amd_chipset.nb_type = 2;
135 } else {
136 amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
137 0x9600, NULL);
138 if (amd_chipset.nb_dev)
139 amd_chipset.nb_type = 3;
140 }
141 }
142
143 amd_chipset.probe_result = 1;
144 printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
145
146 spin_unlock_irqrestore(&amd_lock, flags);
147 return amd_chipset.probe_result;
148}
149EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
150
151/*
152 * The hardware normally enables the A-link power management feature, which
153 * lets the system lower the power consumption in idle states.
154 *
155 * This USB quirk prevents the link going into that lower power state
156 * during isochronous transfers.
157 *
158 * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of
159 * some AMD platforms may stutter or have breaks occasionally.
160 */
161static void usb_amd_quirk_pll(int disable)
162{
163 u32 addr, addr_low, addr_high, val;
164 u32 bit = disable ? 0 : 1;
165 unsigned long flags;
166
167 spin_lock_irqsave(&amd_lock, flags);
168
169 if (disable) {
170 amd_chipset.isoc_reqs++;
171 if (amd_chipset.isoc_reqs > 1) {
172 spin_unlock_irqrestore(&amd_lock, flags);
173 return;
174 }
175 } else {
176 amd_chipset.isoc_reqs--;
177 if (amd_chipset.isoc_reqs > 0) {
178 spin_unlock_irqrestore(&amd_lock, flags);
179 return;
180 }
181 }
182
183 if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
184 outb_p(AB_REG_BAR_LOW, 0xcd6);
185 addr_low = inb_p(0xcd7);
186 outb_p(AB_REG_BAR_HIGH, 0xcd6);
187 addr_high = inb_p(0xcd7);
188 addr = addr_high << 8 | addr_low;
189
190 outl_p(0x30, AB_INDX(addr));
191 outl_p(0x40, AB_DATA(addr));
192 outl_p(0x34, AB_INDX(addr));
193 val = inl_p(AB_DATA(addr));
194 } else if (amd_chipset.sb_type == 3) {
195 pci_read_config_dword(amd_chipset.smbus_dev,
196 AB_REG_BAR_SB700, &addr);
197 outl(AX_INDXC, AB_INDX(addr));
198 outl(0x40, AB_DATA(addr));
199 outl(AX_DATAC, AB_INDX(addr));
200 val = inl(AB_DATA(addr));
201 } else {
202 spin_unlock_irqrestore(&amd_lock, flags);
203 return;
204 }
205
206 if (disable) {
207 val &= ~0x08;
208 val |= (1 << 4) | (1 << 9);
209 } else {
210 val |= 0x08;
211 val &= ~((1 << 4) | (1 << 9));
212 }
213 outl_p(val, AB_DATA(addr));
214
215 if (!amd_chipset.nb_dev) {
216 spin_unlock_irqrestore(&amd_lock, flags);
217 return;
218 }
219
220 if (amd_chipset.nb_type == 1 || amd_chipset.nb_type == 3) {
221 addr = PCIE_P_CNTL;
222 pci_write_config_dword(amd_chipset.nb_dev,
223 NB_PCIE_INDX_ADDR, addr);
224 pci_read_config_dword(amd_chipset.nb_dev,
225 NB_PCIE_INDX_DATA, &val);
226
227 val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
228 val |= bit | (bit << 3) | (bit << 12);
229 val |= ((!bit) << 4) | ((!bit) << 9);
230 pci_write_config_dword(amd_chipset.nb_dev,
231 NB_PCIE_INDX_DATA, val);
232
233 addr = BIF_NB;
234 pci_write_config_dword(amd_chipset.nb_dev,
235 NB_PCIE_INDX_ADDR, addr);
236 pci_read_config_dword(amd_chipset.nb_dev,
237 NB_PCIE_INDX_DATA, &val);
238 val &= ~(1 << 8);
239 val |= bit << 8;
240
241 pci_write_config_dword(amd_chipset.nb_dev,
242 NB_PCIE_INDX_DATA, val);
243 } else if (amd_chipset.nb_type == 2) {
244 addr = NB_PIF0_PWRDOWN_0;
245 pci_write_config_dword(amd_chipset.nb_dev,
246 NB_PCIE_INDX_ADDR, addr);
247 pci_read_config_dword(amd_chipset.nb_dev,
248 NB_PCIE_INDX_DATA, &val);
249 if (disable)
250 val &= ~(0x3f << 7);
251 else
252 val |= 0x3f << 7;
253
254 pci_write_config_dword(amd_chipset.nb_dev,
255 NB_PCIE_INDX_DATA, val);
256
257 addr = NB_PIF0_PWRDOWN_1;
258 pci_write_config_dword(amd_chipset.nb_dev,
259 NB_PCIE_INDX_ADDR, addr);
260 pci_read_config_dword(amd_chipset.nb_dev,
261 NB_PCIE_INDX_DATA, &val);
262 if (disable)
263 val &= ~(0x3f << 7);
264 else
265 val |= 0x3f << 7;
266
267 pci_write_config_dword(amd_chipset.nb_dev,
268 NB_PCIE_INDX_DATA, val);
269 }
270
271 spin_unlock_irqrestore(&amd_lock, flags);
272 return;
273}
274
275void usb_amd_quirk_pll_disable(void)
276{
277 usb_amd_quirk_pll(1);
278}
279EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
280
281void usb_amd_quirk_pll_enable(void)
282{
283 usb_amd_quirk_pll(0);
284}
285EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable);
286
287void usb_amd_dev_put(void)
288{
289 unsigned long flags;
290
291 spin_lock_irqsave(&amd_lock, flags);
292
293 amd_chipset.probe_count--;
294 if (amd_chipset.probe_count > 0) {
295 spin_unlock_irqrestore(&amd_lock, flags);
296 return;
297 }
298
299 if (amd_chipset.nb_dev) {
300 pci_dev_put(amd_chipset.nb_dev);
301 amd_chipset.nb_dev = NULL;
302 }
303 if (amd_chipset.smbus_dev) {
304 pci_dev_put(amd_chipset.smbus_dev);
305 amd_chipset.smbus_dev = NULL;
306 }
307 amd_chipset.nb_type = 0;
308 amd_chipset.sb_type = 0;
309 amd_chipset.isoc_reqs = 0;
310 amd_chipset.probe_result = 0;
311
312 spin_unlock_irqrestore(&amd_lock, flags);
313}
314EXPORT_SYMBOL_GPL(usb_amd_dev_put);
315 55
316/* 56/*
317 * Make sure the controller is completely inactive, unable to 57 * Make sure the controller is completely inactive, unable to
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 4d2118cf1ff8..1564edfff6fe 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -1,26 +1,7 @@
1#ifndef __LINUX_USB_PCI_QUIRKS_H 1#ifndef __LINUX_USB_PCI_QUIRKS_H
2#define __LINUX_USB_PCI_QUIRKS_H 2#define __LINUX_USB_PCI_QUIRKS_H
3 3
4#ifdef CONFIG_PCI
5void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); 4void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
6int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); 5int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
7int usb_amd_find_chipset_info(void);
8void usb_amd_dev_put(void);
9void usb_amd_quirk_pll_disable(void);
10void usb_amd_quirk_pll_enable(void);
11#else
12static inline void usb_amd_quirk_pll_disable(void)
13{
14 return;
15}
16static inline void usb_amd_quirk_pll_enable(void)
17{
18 return;
19}
20static inline void usb_amd_dev_put(void)
21{
22 return;
23}
24#endif /* CONFIG_PCI */
25 6
26#endif /* __LINUX_USB_PCI_QUIRKS_H */ 7#endif /* __LINUX_USB_PCI_QUIRKS_H */