diff options
Diffstat (limited to 'drivers/usb/host/ehci-pci.c')
| -rw-r--r-- | drivers/usb/host/ehci-pci.c | 121 |
1 files changed, 29 insertions, 92 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index dabb2049482..3e86bf4371b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -58,8 +58,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - struct pci_dev *p_smbus; - u8 rev; u32 temp; int retval; @@ -175,22 +173,12 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* SB600 and old version of SB700 have a bug in EHCI controller, * which causes usb devices lose response in some cases. */ - if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) { - p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, - PCI_DEVICE_ID_ATI_SBX00_SMBUS, - NULL); - if (!p_smbus) - break; - rev = p_smbus->revision; - if ((pdev->device == 0x4386) || (rev == 0x3a) - || (rev == 0x3b)) { - u8 tmp; - ehci_info(ehci, "applying AMD SB600/SB700 USB " - "freeze workaround\n"); - pci_read_config_byte(pdev, 0x53, &tmp); - pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); - } - pci_dev_put(p_smbus); + if ((pdev->device == 0x4386 || pdev->device == 0x4396) && + usb_amd_hang_symptom_quirk()) { + u8 tmp; + ehci_info(ehci, "applying AMD SB600/SB700 USB freeze workaround\n"); + pci_read_config_byte(pdev, 0x53, &tmp); + pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); } break; case PCI_VENDOR_ID_NETMOS: @@ -200,6 +188,26 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if (((temp >> 13) & 7) == 1) { + u32 hcs_params = ehci_readl(ehci, + &ehci->caps->hcs_params); + + temp &= 0x1fff; + ehci->debug = hcd->regs + temp; + temp = ehci_readl(ehci, &ehci->debug->control); + ehci_info(ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(hcs_params), + (temp & DBGP_ENABLED) ? " IN USE" : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; + } + } + retval = ehci_setup(hcd); if (retval) return retval; @@ -228,25 +236,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; @@ -291,17 +280,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } } -#ifdef CONFIG_USB_SUSPEND - /* REVISIT: the controller works fine for wakeup iff the root hub - * itself is "globally" suspended, but usbcore currently doesn't - * understand such things. - * - * System suspend currently expects to be able to suspend the entire - * device tree, device-at-a-time. If we failed selective suspend - * reports, system suspend would fail; so the root hub code must claim - * success. That's lying to usbcore, and it matters for runtime - * PM scenarios with selective suspend and remote wakeup... - */ +#ifdef CONFIG_PM_RUNTIME if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); #endif @@ -324,53 +303,11 @@ done: * Also they depend on separate root hub suspend/resume. */ -static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == 0x1E26 || - pdev->device == 0x8C2D || - pdev->device == 0x8C26 || - pdev->device == 0x9C26); -} - -static void ehci_enable_xhci_companion(void) -{ - struct pci_dev *companion = NULL; - - /* The xHCI and EHCI controllers are not on the same PCI slot */ - for_each_pci_dev(companion) { - if (!usb_is_intel_switchable_xhci(companion)) - continue; - usb_enable_xhci_ports(companion); - return; - } -} - static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - /* The BIOS on systems with the Intel Panther Point chipset may or may - * not support xHCI natively. That means that during system resume, it - * may switch the ports back to EHCI so that users can use their - * keyboard to select a kernel from GRUB after resume from hibernate. - * - * The BIOS is supposed to remember whether the OS had xHCI ports - * enabled before resume, and switch the ports back to xHCI when the - * BIOS/OS semaphore is written, but we all know we can't trust BIOS - * writers. - * - * Unconditionally switch the ports back to xHCI after a system resume. - * We can't tell whether the EHCI or xHCI controller will be resumed - * first, so we have to do the port switchover in both drivers. Writing - * a '1' to the port switchover registers should have no effect if the - * port was already switched over. - */ - if (usb_is_intel_switchable_ehci(pdev)) - ehci_enable_xhci_companion(); - if (ehci_resume(hcd, hibernated) != 0) (void) ehci_pci_reinit(ehci, pdev); return 0; @@ -384,7 +321,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) static struct hc_driver __read_mostly ehci_pci_hc_driver; -static const struct ehci_driver_overrides pci_overrides __initdata = { +static const struct ehci_driver_overrides pci_overrides __initconst = { .reset = ehci_pci_setup, }; @@ -412,7 +349,7 @@ static struct pci_driver ehci_pci_driver = { .remove = usb_hcd_pci_remove, .shutdown = usb_hcd_pci_shutdown, -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM .driver = { .pm = &usb_hcd_pci_pm_ops }, |
