Commit 0d436b42 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ff2f0787
...@@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci) ...@@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
*/ */
static void configure_hc(struct uhci_hcd *uhci) static void configure_hc(struct uhci_hcd *uhci)
{ {
struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
/* Set the frame length to the default: 1 ms exactly */ /* Set the frame length to the default: 1 ms exactly */
outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
...@@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci) ...@@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci)
mb(); mb();
/* Enable PIRQ */ /* Enable PIRQ */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
USBLEGSUP_DEFAULT);
/* Disable platform-specific non-PME# wakeup */
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
pci_write_config_byte(pdev, USBRES_INTEL, 0);
} }
...@@ -791,6 +796,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd) ...@@ -791,6 +796,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
int rc = 0; int rc = 0;
dev_dbg(uhci_dev(uhci), "%s\n", __func__); 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,11 +814,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
/* All PCI host controllers are required to disable IRQ generation /* All PCI host controllers are required to disable IRQ generation
* at the source, so we must turn off PIRQ. * at the source, so we must turn off PIRQ.
*/ */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); pci_write_config_word(pdev, USBLEGSUP, 0);
mb();
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
/* FIXME: Enable non-PME# remote wakeup? */ /* Enable platform-specific non-PME# wakeup */
if (do_wakeup) {
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
pci_write_config_byte(pdev, USBRES_INTEL,
USBPORT1EN | USBPORT2EN);
}
done_okay: done_okay:
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
...@@ -831,7 +841,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) ...@@ -831,7 +841,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
* even if the controller was dead. * even if the controller was dead.
*/ */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
mb();
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
...@@ -839,8 +848,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) ...@@ -839,8 +848,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
if (hibernated) if (hibernated)
uhci_hc_died(uhci); uhci_hc_died(uhci);
/* FIXME: Disable non-PME# remote wakeup? */
/* The firmware or a boot kernel may have changed the controller /* The firmware or a boot kernel may have changed the controller
* settings during a system wakeup. Check it and reconfigure * settings during a system wakeup. Check it and reconfigure
* to avoid problems. * to avoid problems.
...@@ -850,12 +857,9 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) ...@@ -850,12 +857,9 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
/* If the controller was dead before, it's back alive now */ /* If the controller was dead before, it's back alive now */
configure_hc(uhci); configure_hc(uhci);
if (uhci->rh_state == UHCI_RH_RESET) { /* Tell the core if the controller had to be reset */
if (uhci->rh_state == UHCI_RH_RESET)
/* The controller had to be reset */
usb_root_hub_lost_power(hcd->self.root_hub); usb_root_hub_lost_power(hcd->self.root_hub);
suspend_rh(uhci, UHCI_RH_SUSPENDED);
}
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
......
...@@ -67,12 +67,17 @@ ...@@ -67,12 +67,17 @@
#define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */ #define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */
#define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */ #define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */
/* Legacy support register */ /* PCI legacy support register */
#define USBLEGSUP 0xc0 #define USBLEGSUP 0xc0
#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
/* PCI Intel-specific resume-enable register */
#define USBRES_INTEL 0xc4
#define USBPORT1EN 0x01
#define USBPORT2EN 0x02
#define UHCI_PTR_BITS cpu_to_le32(0x000F) #define UHCI_PTR_BITS cpu_to_le32(0x000F)
#define UHCI_PTR_TERM cpu_to_le32(0x0001) #define UHCI_PTR_TERM cpu_to_le32(0x0001)
#define UHCI_PTR_QH cpu_to_le32(0x0002) #define UHCI_PTR_QH cpu_to_le32(0x0002)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment