diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-23 12:33:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-23 12:33:02 -0700 |
commit | c44dead70a841d90ddc01968012f323c33217c9e (patch) | |
tree | 85489ebe9b9a3413cd8ee197ffb40c8aa8d97e63 /drivers/usb/host/pci-quirks.c | |
parent | 99dff5856220a02b8711f2e8746413ea6e53ccf6 (diff) | |
parent | d5f6db9e1aff6ccf1876224f152c0268b0c8a992 (diff) | |
download | kernel_samsung_aries-c44dead70a841d90ddc01968012f323c33217c9e.zip kernel_samsung_aries-c44dead70a841d90ddc01968012f323c33217c9e.tar.gz kernel_samsung_aries-c44dead70a841d90ddc01968012f323c33217c9e.tar.bz2 |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (205 commits)
USB: EHCI: Remove SPARC_LEON {read,write}_be definitions from ehci.h
USB: UHCI: Support big endian GRUSBHC HC
sparc: add {read,write}*_be routines
USB: UHCI: Add support for big endian descriptors
USB: UHCI: Use ACCESS_ONCE rather than using a full compiler barrier
USB: UHCI: Add support for big endian mmio
usb-storage: Correct adjust_quirks to include latest flags
usb/isp1760: Fix possible unlink problems
usb/isp1760: Move function isp1760_endpoint_disable() within file.
USB: remove remaining usages of hcd->state from usbcore and fix regression
usb: musb: ux500: add configuration and build options for ux500 dma
usb: musb: ux500: add dma glue layer for ux500
usb: musb: ux500: add dma name for ux500
usb: musb: ux500: add ux500 specific code for gadget side
usb: musb: fix compile error
usb-storage: fix up the unusual_realtek device list
USB: gadget: f_audio: Fix invalid dereference of initdata
EHCI: don't rescan interrupt QHs needlessly
OHCI: fix regression caused by nVidia shutdown workaround
USB: OTG: msm: Free VCCCX regulator even if we can't set the voltage
...
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 151 |
1 files changed, 81 insertions, 70 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 9b166d7..f16c59d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/acpi.h> +#include <linux/dmi.h> #include "pci-quirks.h" #include "xhci-ext-caps.h" @@ -503,14 +504,84 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) iounmap(base); } +static void __devinit ehci_bios_handoff(struct pci_dev *pdev, + void __iomem *op_reg_base, + u32 cap, u8 offset) +{ + int try_handoff = 1, tried_handoff = 0; + + /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90 + * seconds trying the handoff on its unused controller. Skip + * it. */ + if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { + const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME); + const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION); + if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") && + dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133")) + try_handoff = 0; + } + + if (try_handoff && (cap & EHCI_USBLEGSUP_BIOS)) { + dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); + +#if 0 +/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, + * but that seems dubious in general (the BIOS left it off intentionally) + * and is known to prevent some systems from booting. so we won't do this + * unless maybe we can determine when we're on a system that needs SMI forced. + */ + /* BIOS workaround (?): be sure the pre-Linux code + * receives the SMI + */ + pci_read_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, &val); + pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, + val | EHCI_USBLEGCTLSTS_SOOE); +#endif + + /* some systems get upset if this semaphore is + * set for any other reason than forcing a BIOS + * handoff.. + */ + pci_write_config_byte(pdev, offset + 3, 1); + } + + /* if boot firmware now owns EHCI, spin till it hands it over. */ + if (try_handoff) { + int msec = 1000; + while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { + tried_handoff = 1; + msleep(10); + msec -= 10; + pci_read_config_dword(pdev, offset, &cap); + } + } + + if (cap & EHCI_USBLEGSUP_BIOS) { + /* well, possibly buggy BIOS... try to shut it down, + * and hope nothing goes too wrong + */ + if (try_handoff) + dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" + " (BIOS bug?) %08x\n", cap); + pci_write_config_byte(pdev, offset + 2, 0); + } + + /* just in case, always disable EHCI SMIs */ + pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); + + /* If the BIOS ever owned the controller then we can't expect + * any power sessions to remain intact. + */ + if (tried_handoff) + writel(0, op_reg_base + EHCI_CONFIGFLAG); +} + static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) { - int wait_time, delta; void __iomem *base, *op_reg_base; - u32 hcc_params, val; + u32 hcc_params, cap, val; u8 offset, cap_length; - int count = 256/4; - int tried_handoff = 0; + int wait_time, delta, count = 256/4; if (!mmio_resource_enabled(pdev, 0)) return; @@ -529,77 +600,17 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) hcc_params = readl(base + EHCI_HCC_PARAMS); offset = (hcc_params >> 8) & 0xff; while (offset && --count) { - u32 cap; - int msec; - pci_read_config_dword(pdev, offset, &cap); - switch (cap & 0xff) { - case 1: /* BIOS/SMM/... handoff support */ - if ((cap & EHCI_USBLEGSUP_BIOS)) { - dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); -#if 0 -/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, - * but that seems dubious in general (the BIOS left it off intentionally) - * and is known to prevent some systems from booting. so we won't do this - * unless maybe we can determine when we're on a system that needs SMI forced. - */ - /* BIOS workaround (?): be sure the - * pre-Linux code receives the SMI - */ - pci_read_config_dword(pdev, - offset + EHCI_USBLEGCTLSTS, - &val); - pci_write_config_dword(pdev, - offset + EHCI_USBLEGCTLSTS, - val | EHCI_USBLEGCTLSTS_SOOE); -#endif - - /* some systems get upset if this semaphore is - * set for any other reason than forcing a BIOS - * handoff.. - */ - pci_write_config_byte(pdev, offset + 3, 1); - } - - /* if boot firmware now owns EHCI, spin till - * it hands it over. - */ - msec = 1000; - while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { - tried_handoff = 1; - msleep(10); - msec -= 10; - pci_read_config_dword(pdev, offset, &cap); - } - - if (cap & EHCI_USBLEGSUP_BIOS) { - /* well, possibly buggy BIOS... try to shut - * it down, and hope nothing goes too wrong - */ - dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" - " (BIOS bug?) %08x\n", cap); - pci_write_config_byte(pdev, offset + 2, 0); - } - - /* just in case, always disable EHCI SMIs */ - pci_write_config_dword(pdev, - offset + EHCI_USBLEGCTLSTS, - 0); - - /* If the BIOS ever owned the controller then we - * can't expect any power sessions to remain intact. - */ - if (tried_handoff) - writel(0, op_reg_base + EHCI_CONFIGFLAG); + switch (cap & 0xff) { + case 1: + ehci_bios_handoff(pdev, op_reg_base, cap, offset); break; - case 0: /* illegal reserved capability */ - cap = 0; - /* FALLTHROUGH */ + case 0: /* Illegal reserved cap, set cap=0 so we exit */ + cap = 0; /* then fallthrough... */ default: dev_warn(&pdev->dev, "EHCI: unrecognized capability " - "%02x\n", cap & 0xff); - break; + "%02x\n", cap & 0xff); } offset = (cap >> 8) & 0xff; } |