#define        INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
-/* for ASPM quirk of ISOC on AMD SB800 */
-static struct pci_dev *amd_nb_dev;
-
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
 #include "ehci-dbg.c"
+#include "pci-quirks.h"
 
 /*-------------------------------------------------------------------------*/
 
        spin_unlock_irq (&ehci->lock);
        ehci_mem_cleanup (ehci);
 
-       if (amd_nb_dev) {
-               pci_dev_put(amd_nb_dev);
-               amd_nb_dev = NULL;
-       }
+       if (ehci->amd_pll_fix == 1)
+               usb_amd_dev_put();
 
 #ifdef EHCI_STATS
        ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
 
        return 0;
 }
 
-static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci)
-{
-       struct pci_dev *amd_smbus_dev;
-       u8 rev = 0;
-
-       amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
-       if (amd_smbus_dev) {
-               pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
-               if (rev < 0x40) {
-                       pci_dev_put(amd_smbus_dev);
-                       amd_smbus_dev = NULL;
-                       return 0;
-               }
-       } else {
-               amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL);
-               if (!amd_smbus_dev)
-                       return 0;
-               pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
-               if (rev < 0x11 || rev > 0x18) {
-                       pci_dev_put(amd_smbus_dev);
-                       amd_smbus_dev = NULL;
-                       return 0;
-               }
-       }
-
-       if (!amd_nb_dev)
-               amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
-
-       ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n");
-
-       pci_dev_put(amd_smbus_dev);
-       amd_smbus_dev = NULL;
-
-       return 1;
-}
-
 /* called during probe() after chip reset completes */
 static int ehci_pci_setup(struct usb_hcd *hcd)
 {
        /* cache this readonly data; minimize chip reads */
        ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
-       if (ehci_quirk_amd_hudson(ehci))
-               ehci->amd_l1_fix = 1;
-
        retval = ehci_halt(ehci);
        if (retval)
                return retval;
                }
                break;
        case PCI_VENDOR_ID_AMD:
+               /* AMD PLL quirk */
+               if (usb_amd_find_chipset_info())
+                       ehci->amd_pll_fix = 1;
                /* AMD8111 EHCI doesn't work, according to AMD errata */
                if (pdev->device == 0x7463) {
                        ehci_info(ehci, "ignoring AMD8111 (errata)\n");
                }
                break;
        case PCI_VENDOR_ID_ATI:
+               /* AMD PLL quirk */
+               if (usb_amd_find_chipset_info())
+                       ehci->amd_pll_fix = 1;
                /* SB600 and old version of SB700 have a bug in EHCI controller,
                 * which causes usb devices lose response in some cases.
                 */
 
        *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
-#define AB_REG_BAR_LOW 0xe0
-#define AB_REG_BAR_HIGH 0xe1
-#define AB_INDX(addr) ((addr) + 0x00)
-#define AB_DATA(addr) ((addr) + 0x04)
-#define NB_PCIE_INDX_ADDR 0xe0
-#define NB_PCIE_INDX_DATA 0xe4
-#define NB_PIF0_PWRDOWN_0 0x01100012
-#define NB_PIF0_PWRDOWN_1 0x01100013
-
-static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
-{
-       u32 addr, addr_low, addr_high, val;
-
-       outb_p(AB_REG_BAR_LOW, 0xcd6);
-       addr_low = inb_p(0xcd7);
-       outb_p(AB_REG_BAR_HIGH, 0xcd6);
-       addr_high = inb_p(0xcd7);
-       addr = addr_high << 8 | addr_low;
-       outl_p(0x30, AB_INDX(addr));
-       outl_p(0x40, AB_DATA(addr));
-       outl_p(0x34, AB_INDX(addr));
-       val = inl_p(AB_DATA(addr));
-
-       if (disable) {
-               val &= ~0x8;
-               val |= (1 << 4) | (1 << 9);
-       } else {
-               val |= 0x8;
-               val &= ~((1 << 4) | (1 << 9));
-       }
-       outl_p(val, AB_DATA(addr));
-
-       if (amd_nb_dev) {
-               addr = NB_PIF0_PWRDOWN_0;
-               pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
-               pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
-               if (disable)
-                       val &= ~(0x3f << 7);
-               else
-                       val |= 0x3f << 7;
-
-               pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
-
-               addr = NB_PIF0_PWRDOWN_1;
-               pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
-               pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
-               if (disable)
-                       val &= ~(0x3f << 7);
-               else
-                       val |= 0x3f << 7;
-
-               pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
-       }
-
-       return;
-}
-
 /* fit urb's itds into the selected schedule slot; activate as needed */
 static int
 itd_link_urb (
        }
 
        if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-               if (ehci->amd_l1_fix == 1)
-                       ehci_quirk_amd_L1(ehci, 1);
+               if (ehci->amd_pll_fix == 1)
+                       usb_amd_quirk_pll_disable();
        }
 
        ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
        ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
        if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-               if (ehci->amd_l1_fix == 1)
-                       ehci_quirk_amd_L1(ehci, 0);
+               if (ehci->amd_pll_fix == 1)
+                       usb_amd_quirk_pll_enable();
        }
 
        if (unlikely(list_is_singular(&stream->td_list))) {
        }
 
        if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-               if (ehci->amd_l1_fix == 1)
-                       ehci_quirk_amd_L1(ehci, 1);
+               if (ehci->amd_pll_fix == 1)
+                       usb_amd_quirk_pll_disable();
        }
 
        ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
        ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
        if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-               if (ehci->amd_l1_fix == 1)
-                       ehci_quirk_amd_L1(ehci, 0);
+               if (ehci->amd_pll_fix == 1)
+                       usb_amd_quirk_pll_enable();
        }
 
        if (list_is_singular(&stream->td_list)) {
 
        unsigned                has_amcc_usb23:1;
        unsigned                need_io_watchdog:1;
        unsigned                broken_periodic:1;
-       unsigned                amd_l1_fix:1;
+       unsigned                amd_pll_fix:1;
        unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
        unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
 
 
 #define        STATECHANGE_DELAY       msecs_to_jiffies(300)
 
 #include "ohci.h"
+#include "pci-quirks.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
 #endif
 
 #ifdef CONFIG_PCI
-static void quirk_amd_pll(int state);
-static void amd_iso_dev_put(void);
 static void sb800_prefetch(struct ohci_hcd *ohci, int on);
 #else
-static inline void quirk_amd_pll(int state)
-{
-       return;
-}
-static inline void amd_iso_dev_put(void)
-{
-       return;
-}
 static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
        return;
        if (quirk_zfmicro(ohci))
                del_timer(&ohci->unlink_watchdog);
        if (quirk_amdiso(ohci))
-               amd_iso_dev_put();
+               usb_amd_dev_put();
 
        remove_debug_files (ohci);
        ohci_mem_cleanup (ohci);
 
 #include <linux/io.h>
 
 
-/* constants used to work around PM-related transfer
- * glitches in some AMD 700 series southbridges
- */
-#define AB_REG_BAR     0xf0
-#define AB_INDX(addr)  ((addr) + 0x00)
-#define AB_DATA(addr)  ((addr) + 0x04)
-#define AX_INDXC       0X30
-#define AX_DATAC       0x34
-
-#define NB_PCIE_INDX_ADDR      0xe0
-#define NB_PCIE_INDX_DATA      0xe4
-#define PCIE_P_CNTL            0x10040
-#define BIF_NB                 0x10002
-
-static struct pci_dev *amd_smbus_dev;
-static struct pci_dev *amd_hb_dev;
-static int amd_ohci_iso_count;
-
 /*-------------------------------------------------------------------------*/
 
 static int broken_suspend(struct usb_hcd *hcd)
 static int ohci_quirk_amd700(struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       struct pci_dev *amd_smbus_dev;
        u8 rev = 0;
 
-       if (!amd_smbus_dev)
-               amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
-                               PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+       if (usb_amd_find_chipset_info())
+               ohci->flags |= OHCI_QUIRK_AMD_PLL;
+
+       amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+                       PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
        if (!amd_smbus_dev)
                return 0;
 
                ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
        }
 
-       if ((rev > 0x3b) || (rev < 0x30)) {
-               pci_dev_put(amd_smbus_dev);
-               amd_smbus_dev = NULL;
-               return 0;
-       }
-
-       amd_ohci_iso_count++;
-
-       if (!amd_hb_dev)
-               amd_hb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9600, NULL);
-
-       ohci->flags |= OHCI_QUIRK_AMD_ISO;
-       ohci_dbg(ohci, "enabled AMD ISO transfers quirk\n");
+       pci_dev_put(amd_smbus_dev);
+       amd_smbus_dev = NULL;
 
        return 0;
 }
        return 0;
 }
 
-/*
- * The hardware normally enables the A-link power management feature, which
- * lets the system lower the power consumption in idle states.
- *
- * Assume the system is configured to have USB 1.1 ISO transfers going
- * to or from a USB device.  Without this quirk, that stream may stutter
- * or have breaks occasionally.  For transfers going to speakers, this
- * makes a very audible mess...
- *
- * That audio playback corruption is due to the audio stream getting
- * interrupted occasionally when the link goes in lower power state
- * This USB quirk prevents the link going into that lower power state
- * during audio playback or other ISO operations.
- */
-static void quirk_amd_pll(int on)
-{
-       u32 addr;
-       u32 val;
-       u32 bit = (on > 0) ? 1 : 0;
-
-       pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr);
-
-       /* BIT names/meanings are NDA-protected, sorry ... */
-
-       outl(AX_INDXC, AB_INDX(addr));
-       outl(0x40, AB_DATA(addr));
-       outl(AX_DATAC, AB_INDX(addr));
-       val = inl(AB_DATA(addr));
-       val &= ~((1 << 3) | (1 << 4) | (1 << 9));
-       val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9);
-       outl(val, AB_DATA(addr));
-
-       if (amd_hb_dev) {
-               addr = PCIE_P_CNTL;
-               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
-
-               pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
-               val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
-               val |= bit | (bit << 3) | (bit << 12);
-               val |= ((!bit) << 4) | ((!bit) << 9);
-               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
-
-               addr = BIF_NB;
-               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
-
-               pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
-               val &= ~(1 << 8);
-               val |= bit << 8;
-               pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
-       }
-}
-
-static void amd_iso_dev_put(void)
-{
-       amd_ohci_iso_count--;
-       if (amd_ohci_iso_count == 0) {
-               if (amd_smbus_dev) {
-                       pci_dev_put(amd_smbus_dev);
-                       amd_smbus_dev = NULL;
-               }
-               if (amd_hb_dev) {
-                       pci_dev_put(amd_hb_dev);
-                       amd_hb_dev = NULL;
-               }
-       }
-
-}
-
 static void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
        struct pci_dev *pdev;
 
                ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
                if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
                        if (quirk_amdiso(ohci))
-                               quirk_amd_pll(1);
+                               usb_amd_quirk_pll_enable();
                        if (quirk_amdprefetch(ohci))
                                sb800_prefetch(ohci, 0);
                }
                }
                if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
                        if (quirk_amdiso(ohci))
-                               quirk_amd_pll(0);
+                               usb_amd_quirk_pll_disable();
                        if (quirk_amdprefetch(ohci))
                                sb800_prefetch(ohci, 1);
                }
 
 #define        OHCI_QUIRK_NEC          0x40                    /* lost interrupts */
 #define        OHCI_QUIRK_FRAME_NO     0x80                    /* no big endian frame_no shift */
 #define        OHCI_QUIRK_HUB_POWER    0x100                   /* distrust firmware power/oc setup */
-#define        OHCI_QUIRK_AMD_ISO      0x200                   /* ISO transfers*/
+#define        OHCI_QUIRK_AMD_PLL      0x200                   /* AMD PLL quirk*/
 #define        OHCI_QUIRK_AMD_PREFETCH 0x400                   /* pre-fetch for ISO transfer */
 #define        OHCI_QUIRK_SHUTDOWN     0x800                   /* nVidia power bug */
        // there are also chip quirks/bugs in init logic
 }
 static inline int quirk_amdiso(struct ohci_hcd *ohci)
 {
-       return ohci->flags & OHCI_QUIRK_AMD_ISO;
+       return ohci->flags & OHCI_QUIRK_AMD_PLL;
 }
 static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
 {
 
 #define EHCI_USBLEGCTLSTS      4               /* legacy control/status */
 #define EHCI_USBLEGCTLSTS_SOOE (1 << 13)       /* SMI on ownership change */
 
+/* AMD quirk use */
+#define        AB_REG_BAR_LOW          0xe0
+#define        AB_REG_BAR_HIGH         0xe1
+#define        AB_REG_BAR_SB700        0xf0
+#define        AB_INDX(addr)           ((addr) + 0x00)
+#define        AB_DATA(addr)           ((addr) + 0x04)
+#define        AX_INDXC                0x30
+#define        AX_DATAC                0x34
+
+#define        NB_PCIE_INDX_ADDR       0xe0
+#define        NB_PCIE_INDX_DATA       0xe4
+#define        PCIE_P_CNTL             0x10040
+#define        BIF_NB                  0x10002
+#define        NB_PIF0_PWRDOWN_0       0x01100012
+#define        NB_PIF0_PWRDOWN_1       0x01100013
+
+static struct amd_chipset_info {
+       struct pci_dev  *nb_dev;
+       struct pci_dev  *smbus_dev;
+       int nb_type;
+       int sb_type;
+       int isoc_reqs;
+       int probe_count;
+       int probe_result;
+} amd_chipset;
+
+static DEFINE_SPINLOCK(amd_lock);
+
+int usb_amd_find_chipset_info(void)
+{
+       u8 rev = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&amd_lock, flags);
+
+       amd_chipset.probe_count++;
+       /* probe only once */
+       if (amd_chipset.probe_count > 1) {
+               spin_unlock_irqrestore(&amd_lock, flags);
+               return amd_chipset.probe_result;
+       }
+
+       amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
+       if (amd_chipset.smbus_dev) {
+               rev = amd_chipset.smbus_dev->revision;
+               if (rev >= 0x40)
+                       amd_chipset.sb_type = 1;
+               else if (rev >= 0x30 && rev <= 0x3b)
+                       amd_chipset.sb_type = 3;
+       } else {
+               amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                                                       0x780b, NULL);
+               if (!amd_chipset.smbus_dev) {
+                       spin_unlock_irqrestore(&amd_lock, flags);
+                       return 0;
+               }
+               rev = amd_chipset.smbus_dev->revision;
+               if (rev >= 0x11 && rev <= 0x18)
+                       amd_chipset.sb_type = 2;
+       }
+
+       if (amd_chipset.sb_type == 0) {
+               if (amd_chipset.smbus_dev) {
+                       pci_dev_put(amd_chipset.smbus_dev);
+                       amd_chipset.smbus_dev = NULL;
+               }
+               spin_unlock_irqrestore(&amd_lock, flags);
+               return 0;
+       }
+
+       amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL);
+       if (amd_chipset.nb_dev) {
+               amd_chipset.nb_type = 1;
+       } else {
+               amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                                                       0x1510, NULL);
+               if (amd_chipset.nb_dev) {
+                       amd_chipset.nb_type = 2;
+               } else  {
+                       amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                                                               0x9600, NULL);
+                       if (amd_chipset.nb_dev)
+                               amd_chipset.nb_type = 3;
+               }
+       }
+
+       amd_chipset.probe_result = 1;
+       printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
+
+       spin_unlock_irqrestore(&amd_lock, flags);
+       return amd_chipset.probe_result;
+}
+EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
+
+/*
+ * The hardware normally enables the A-link power management feature, which
+ * lets the system lower the power consumption in idle states.
+ *
+ * This USB quirk prevents the link going into that lower power state
+ * during isochronous transfers.
+ *
+ * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of
+ * some AMD platforms may stutter or have breaks occasionally.
+ */
+static void usb_amd_quirk_pll(int disable)
+{
+       u32 addr, addr_low, addr_high, val;
+       u32 bit = disable ? 0 : 1;
+       unsigned long flags;
+
+       spin_lock_irqsave(&amd_lock, flags);
+
+       if (disable) {
+               amd_chipset.isoc_reqs++;
+               if (amd_chipset.isoc_reqs > 1) {
+                       spin_unlock_irqrestore(&amd_lock, flags);
+                       return;
+               }
+       } else {
+               amd_chipset.isoc_reqs--;
+               if (amd_chipset.isoc_reqs > 0) {
+                       spin_unlock_irqrestore(&amd_lock, flags);
+                       return;
+               }
+       }
+
+       if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
+               outb_p(AB_REG_BAR_LOW, 0xcd6);
+               addr_low = inb_p(0xcd7);
+               outb_p(AB_REG_BAR_HIGH, 0xcd6);
+               addr_high = inb_p(0xcd7);
+               addr = addr_high << 8 | addr_low;
+
+               outl_p(0x30, AB_INDX(addr));
+               outl_p(0x40, AB_DATA(addr));
+               outl_p(0x34, AB_INDX(addr));
+               val = inl_p(AB_DATA(addr));
+       } else if (amd_chipset.sb_type == 3) {
+               pci_read_config_dword(amd_chipset.smbus_dev,
+                                       AB_REG_BAR_SB700, &addr);
+               outl(AX_INDXC, AB_INDX(addr));
+               outl(0x40, AB_DATA(addr));
+               outl(AX_DATAC, AB_INDX(addr));
+               val = inl(AB_DATA(addr));
+       } else {
+               spin_unlock_irqrestore(&amd_lock, flags);
+               return;
+       }
+
+       if (disable) {
+               val &= ~0x08;
+               val |= (1 << 4) | (1 << 9);
+       } else {
+               val |= 0x08;
+               val &= ~((1 << 4) | (1 << 9));
+       }
+       outl_p(val, AB_DATA(addr));
+
+       if (!amd_chipset.nb_dev) {
+               spin_unlock_irqrestore(&amd_lock, flags);
+               return;
+       }
+
+       if (amd_chipset.nb_type == 1 || amd_chipset.nb_type == 3) {
+               addr = PCIE_P_CNTL;
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_ADDR, addr);
+               pci_read_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, &val);
+
+               val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
+               val |= bit | (bit << 3) | (bit << 12);
+               val |= ((!bit) << 4) | ((!bit) << 9);
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, val);
+
+               addr = BIF_NB;
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_ADDR, addr);
+               pci_read_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, &val);
+               val &= ~(1 << 8);
+               val |= bit << 8;
+
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, val);
+       } else if (amd_chipset.nb_type == 2) {
+               addr = NB_PIF0_PWRDOWN_0;
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_ADDR, addr);
+               pci_read_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, &val);
+               if (disable)
+                       val &= ~(0x3f << 7);
+               else
+                       val |= 0x3f << 7;
+
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, val);
+
+               addr = NB_PIF0_PWRDOWN_1;
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_ADDR, addr);
+               pci_read_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, &val);
+               if (disable)
+                       val &= ~(0x3f << 7);
+               else
+                       val |= 0x3f << 7;
+
+               pci_write_config_dword(amd_chipset.nb_dev,
+                                       NB_PCIE_INDX_DATA, val);
+       }
+
+       spin_unlock_irqrestore(&amd_lock, flags);
+       return;
+}
+
+void usb_amd_quirk_pll_disable(void)
+{
+       usb_amd_quirk_pll(1);
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
+
+void usb_amd_quirk_pll_enable(void)
+{
+       usb_amd_quirk_pll(0);
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable);
+
+void usb_amd_dev_put(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&amd_lock, flags);
+
+       amd_chipset.probe_count--;
+       if (amd_chipset.probe_count > 0) {
+               spin_unlock_irqrestore(&amd_lock, flags);
+               return;
+       }
+
+       if (amd_chipset.nb_dev) {
+               pci_dev_put(amd_chipset.nb_dev);
+               amd_chipset.nb_dev = NULL;
+       }
+       if (amd_chipset.smbus_dev) {
+               pci_dev_put(amd_chipset.smbus_dev);
+               amd_chipset.smbus_dev = NULL;
+       }
+       amd_chipset.nb_type = 0;
+       amd_chipset.sb_type = 0;
+       amd_chipset.isoc_reqs = 0;
+       amd_chipset.probe_result = 0;
+
+       spin_unlock_irqrestore(&amd_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_amd_dev_put);
 
 /*
  * Make sure the controller is completely inactive, unable to
 
 #ifndef __LINUX_USB_PCI_QUIRKS_H
 #define __LINUX_USB_PCI_QUIRKS_H
 
+#ifdef CONFIG_PCI
 void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
 int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+int usb_amd_find_chipset_info(void);
+void usb_amd_dev_put(void);
+void usb_amd_quirk_pll_disable(void);
+void usb_amd_quirk_pll_enable(void);
+#else
+static inline void usb_amd_quirk_pll_disable(void) {}
+static inline void usb_amd_quirk_pll_enable(void) {}
+static inline void usb_amd_dev_put(void) {}
+#endif  /* CONFIG_PCI */
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */