aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-06-25 14:02:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:38 -0400
commit0d436b425e07f9e4b0fe571cec061f5d136f1d8b (patch)
treef1ebf7929aaf1b4b5e96e1182085e8924e2d0d50 /drivers
parentff2f07874362d34684296f2bd5547a099f33c6d4 (diff)
USB: UHCI: add support for Intel's wakeup flags
This patch (as1396) adds code to uhci-hcd to support the vendor-specific wakeup settings found in Intel's ICHx hardware. A couple of unnecessary memory barriers are removed. And the root hub isn't put back into the "suspended" state if power was lost during a system sleep -- there's not much point in doing so because the root hub will be resumed shortly. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/uhci-hcd.c30
-rw-r--r--drivers/usb/host/uhci-hcd.h7
2 files changed, 23 insertions, 14 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 9d4d81248f96..b04506036b64 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
176 */ 176 */
177static void configure_hc(struct uhci_hcd *uhci) 177static void configure_hc(struct uhci_hcd *uhci)
178{ 178{
179 struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
180
179 /* Set the frame length to the default: 1 ms exactly */ 181 /* Set the frame length to the default: 1 ms exactly */
180 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); 182 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
181 183
@@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci)
191 mb(); 193 mb();
192 194
193 /* Enable PIRQ */ 195 /* Enable PIRQ */
194 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 196 pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
195 USBLEGSUP_DEFAULT); 197
198 /* Disable platform-specific non-PME# wakeup */
199 if (pdev->vendor == PCI_VENDOR_ID_INTEL)
200 pci_write_config_byte(pdev, USBRES_INTEL, 0);
196} 201}
197 202
198 203
@@ -791,6 +796,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
791static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) 796static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
792{ 797{
793 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 798 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
799 struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
794 int rc = 0; 800 int rc = 0;
795 801
796 dev_dbg(uhci_dev(uhci), "%s\n", __func__); 802 dev_dbg(uhci_dev(uhci), "%s\n", __func__);
@@ -808,11 +814,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
808 /* All PCI host controllers are required to disable IRQ generation 814 /* All PCI host controllers are required to disable IRQ generation
809 * at the source, so we must turn off PIRQ. 815 * at the source, so we must turn off PIRQ.
810 */ 816 */
811 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); 817 pci_write_config_word(pdev, USBLEGSUP, 0);
812 mb();
813 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); 818 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
814 819
815 /* FIXME: Enable non-PME# remote wakeup? */ 820 /* Enable platform-specific non-PME# wakeup */
821 if (do_wakeup) {
822 if (pdev->vendor == PCI_VENDOR_ID_INTEL)
823 pci_write_config_byte(pdev, USBRES_INTEL,
824 USBPORT1EN | USBPORT2EN);
825 }
816 826
817done_okay: 827done_okay:
818 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 828 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -831,7 +841,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
831 * even if the controller was dead. 841 * even if the controller was dead.
832 */ 842 */
833 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 843 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
834 mb();
835 844
836 spin_lock_irq(&uhci->lock); 845 spin_lock_irq(&uhci->lock);
837 846
@@ -839,8 +848,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
839 if (hibernated) 848 if (hibernated)
840 uhci_hc_died(uhci); 849 uhci_hc_died(uhci);
841 850
842 /* FIXME: Disable non-PME# remote wakeup? */
843
844 /* The firmware or a boot kernel may have changed the controller 851 /* The firmware or a boot kernel may have changed the controller
845 * settings during a system wakeup. Check it and reconfigure 852 * settings during a system wakeup. Check it and reconfigure
846 * to avoid problems. 853 * to avoid problems.
@@ -850,12 +857,9 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
850 /* If the controller was dead before, it's back alive now */ 857 /* If the controller was dead before, it's back alive now */
851 configure_hc(uhci); 858 configure_hc(uhci);
852 859
853 if (uhci->rh_state == UHCI_RH_RESET) { 860 /* Tell the core if the controller had to be reset */
854 861 if (uhci->rh_state == UHCI_RH_RESET)
855 /* The controller had to be reset */
856 usb_root_hub_lost_power(hcd->self.root_hub); 862 usb_root_hub_lost_power(hcd->self.root_hub);
857 suspend_rh(uhci, UHCI_RH_SUSPENDED);
858 }
859 863
860 spin_unlock_irq(&uhci->lock); 864 spin_unlock_irq(&uhci->lock);
861 865
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 26bd1b2bcbfc..49bf2790f9c2 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -67,12 +67,17 @@
67#define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */ 67#define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */
68#define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */ 68#define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */
69 69
70/* Legacy support register */ 70/* PCI legacy support register */
71#define USBLEGSUP 0xc0 71#define USBLEGSUP 0xc0
72#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ 72#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
73#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ 73#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
74#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ 74#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
75 75
76/* PCI Intel-specific resume-enable register */
77#define USBRES_INTEL 0xc4
78#define USBPORT1EN 0x01
79#define USBPORT2EN 0x02
80
76#define UHCI_PTR_BITS cpu_to_le32(0x000F) 81#define UHCI_PTR_BITS cpu_to_le32(0x000F)
77#define UHCI_PTR_TERM cpu_to_le32(0x0001) 82#define UHCI_PTR_TERM cpu_to_le32(0x0001)
78#define UHCI_PTR_QH cpu_to_le32(0x0002) 83#define UHCI_PTR_QH cpu_to_le32(0x0002)