#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 sb800_prefetch(struct ohci_hcd *ohci, int on)
+{
+       return;
+}
 #endif
 
 
 
                return 0;
 
        pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+
+       /* SB800 needs pre-fetch fix */
+       if ((rev >= 0x40) && (rev <= 0x4f)) {
+               ohci->flags |= OHCI_QUIRK_AMD_PREFETCH;
+               ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
+       }
+
        if ((rev > 0x3b) || (rev < 0x30)) {
                pci_dev_put(amd_smbus_dev);
                amd_smbus_dev = NULL;
 
 }
 
+static void sb800_prefetch(struct ohci_hcd *ohci, int on)
+{
+       struct pci_dev *pdev;
+       u16 misc;
+
+       pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller);
+       pci_read_config_word(pdev, 0x50, &misc);
+       if (on == 0)
+               pci_write_config_word(pdev, 0x50, misc & 0xfcff);
+       else
+               pci_write_config_word(pdev, 0x50, misc | 0x0300);
+}
+
 /* List of quirks for OHCI */
 static const struct pci_device_id ohci_pci_quirks[] = {
        {
 
        switch (usb_pipetype (urb->pipe)) {
        case PIPE_ISOCHRONOUS:
                ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
-               if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
-                               && quirk_amdiso(ohci))
-                       quirk_amd_pll(1);
+               if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
+                       if (quirk_amdiso(ohci))
+                               quirk_amd_pll(1);
+                       if (quirk_amdprefetch(ohci))
+                               sb800_prefetch(ohci, 0);
+               }
                break;
        case PIPE_INTERRUPT:
                ohci_to_hcd(ohci)->self.bandwidth_int_reqs--;
                                data + urb->iso_frame_desc [cnt].offset,
                                urb->iso_frame_desc [cnt].length, urb, cnt);
                }
-               if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
-                               && quirk_amdiso(ohci))
-                       quirk_amd_pll(0);
+               if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
+                       if (quirk_amdiso(ohci))
+                               quirk_amd_pll(0);
+                       if (quirk_amdprefetch(ohci))
+                               sb800_prefetch(ohci, 1);
+               }
                periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0
                        && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0;
                break;
 
 #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_PREFETCH 0x400                   /* pre-fetch for ISO transfer */
        // there are also chip quirks/bugs in init logic
 
        struct work_struct      nec_work;       /* Worker for NEC quirk */
 {
        return ohci->flags & OHCI_QUIRK_AMD_ISO;
 }
+static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
+{
+       return ohci->flags & OHCI_QUIRK_AMD_PREFETCH;
+}
 #else
 static inline int quirk_nec(struct ohci_hcd *ohci)
 {
 {
        return 0;
 }
+static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
+{
+       return 0;
+}
 #endif
 
 /* convert between an hcd pointer and the corresponding ohci_hcd */