Merge ../linux-2.6
[powerpc.git] / drivers / usb / core / hcd-pci.c
index 84d9e69..29b5b2a 100644 (file)
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/usb.h>
+
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <linux/usb.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#endif
 
 #include "usb.h"
 #include "hcd.h"
@@ -218,6 +219,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
                        goto done;
                }
        }
+       synchronize_irq(dev->irq);
 
        /* FIXME until the generic PM interfaces change a lot more, this
         * can't use PCI D1 and D2 states.  For example, the confusion
@@ -284,8 +286,22 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
        }
 
 done:
-       if (retval == 0)
+       if (retval == 0) {
                dev->dev.power.power_state = PMSG_SUSPEND;
+
+#ifdef CONFIG_PPC_PMAC
+               /* Disable ASIC clocks for USB */
+               if (_machine == _MACH_Pmac) {
+                       struct device_node      *of_node;
+
+                       of_node = pci_device_to_OF_node (dev);
+                       if (of_node)
+                               pmac_call_feature(PMAC_FTR_USB_ENABLE,
+                                                       of_node, 0, 0);
+               }
+#endif
+       }
+
        return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_suspend);
@@ -308,6 +324,18 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
                return 0;
        }
 
+#ifdef CONFIG_PPC_PMAC
+       /* Reenable ASIC clocks for USB */
+       if (_machine == _MACH_Pmac) {
+               struct device_node *of_node;
+
+               of_node = pci_device_to_OF_node (dev);
+               if (of_node)
+                       pmac_call_feature (PMAC_FTR_USB_ENABLE,
+                                               of_node, 0, 1);
+       }
+#endif
+
        /* NOTE:  chip docs cover clean "real suspend" cases (what Linux
         * calls "standby", "suspend to RAM", and so on).  There are also
         * dirty cases when swsusp fakes a suspend in "shutdown" mode.
@@ -365,7 +393,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 
        dev->dev.power.power_state = PMSG_ON;
 
-       hcd->saw_irq = 0;
+       clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
 
        if (hcd->driver->resume) {
                retval = hcd->driver->resume(hcd);