diff options
Diffstat (limited to 'drivers/usb/host/ehci-pci.c')
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 160 |
1 files changed, 79 insertions, 81 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 6e767bce060..21e5f963f33 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd) u32 temp; int retval; + ehci->caps = hcd->regs; + + /* + * ehci_init() causes memory for DMA transfers to be + * allocated. Thus, any vendor-specific workarounds based on + * limiting the type of memory used for DMA transfers must + * happen before ehci_setup() is called. + * + * Most other workarounds can be done either before or after + * init and reset; they are located here too. + */ switch (pdev->vendor) { case PCI_VENDOR_ID_TOSHIBA_2: /* celleb's companion chip */ @@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) #endif } break; - } - - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* ehci_init() causes memory for DMA transfers to be - * allocated. Thus, any vendor-specific workarounds based on - * limiting the type of memory used for DMA transfers must - * happen before ehci_init() is called. */ - switch (pdev->vendor) { case PCI_VENDOR_ID_NVIDIA: /* NVidia reports that certain chips don't handle * QH, ITD, or SITD addresses above 2GB. (But TD, @@ -95,61 +92,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci_warn(ehci, "can't enable NVidia " "workaround for >2GB RAM\n"); break; - } - break; - } - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - retval = ehci_halt(ehci); - if (retval) - return retval; - - if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) || - (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) { - /* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may - * read/write memory space which does not belong to it when - * there is NULL pointer with T-bit set to 1 in the frame list - * table. To avoid the issue, the frame list link pointer - * should always contain a valid pointer to a inactive qh. + /* Some NForce2 chips have problems with selective suspend; + * fixed in newer silicon. */ - ehci->use_dummy_qh = 1; - ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI " - "dummy qh workaround\n"); - } - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - switch (pdev->vendor) { - case PCI_VENDOR_ID_NEC: - ehci->need_io_watchdog = 0; + case 0x0068: + if (pdev->revision < 0xa4) + ehci->no_selective_suspend = 1; + break; + } break; case PCI_VENDOR_ID_INTEL: - ehci->need_io_watchdog = 0; ehci->fs_i_thresh = 1; if (pdev->device == 0x27cc) { ehci->broken_periodic = 1; ehci_info(ehci, "using broken periodic workaround\n"); } - if (pdev->device == 0x0806 || pdev->device == 0x0811 - || pdev->device == 0x0829) { - ehci_info(ehci, "disable lpm for langwell/penwell\n"); - ehci->has_lpm = 0; - } - if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) { + if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) hcd->has_tt = 1; - tdi_reset(ehci); - } break; case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) hcd->has_tt = 1; - tdi_reset(ehci); - } break; case PCI_VENDOR_ID_AMD: /* AMD PLL quirk */ @@ -161,28 +125,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd) retval = -EIO; goto done; } - break; - case PCI_VENDOR_ID_NVIDIA: - switch (pdev->device) { - /* Some NForce2 chips have problems with selective suspend; - * fixed in newer silicon. - */ - case 0x0068: - if (pdev->revision < 0xa4) - ehci->no_selective_suspend = 1; - break; - /* MCP89 chips on the MacBookAir3,1 give EPROTO when - * fetching device descriptors unless LPM is disabled. - * There are also intermittent problems enumerating - * devices with PPCD enabled. + /* + * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may + * read/write memory space which does not belong to it when + * there is NULL pointer with T-bit set to 1 in the frame list + * table. To avoid the issue, the frame list link pointer + * should always contain a valid pointer to a inactive qh. */ - case 0x0d9d: - ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); - ehci->has_lpm = 0; - ehci->has_ppcd = 0; - ehci->command &= ~CMD_PPCEE; - break; + if (pdev->device == 0x7808) { + ehci->use_dummy_qh = 1; + ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); } break; case PCI_VENDOR_ID_VIA: @@ -203,6 +156,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* AMD PLL quirk */ if (usb_amd_find_chipset_info()) ehci->amd_pll_fix = 1; + + /* + * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may + * read/write memory space which does not belong to it when + * there is NULL pointer with T-bit set to 1 in the frame list + * table. To avoid the issue, the frame list link pointer + * should always contain a valid pointer to a inactive qh. + */ + if (pdev->device == 0x4396) { + ehci->use_dummy_qh = 1; + ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); + } /* SB600 and old version of SB700 have a bug in EHCI controller, * which causes usb devices lose response in some cases. */ @@ -231,6 +196,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } + retval = ehci_setup(hcd); + if (retval) + return retval; + + /* These workarounds need to be applied after ehci_setup() */ + switch (pdev->vendor) { + case PCI_VENDOR_ID_NEC: + ehci->need_io_watchdog = 0; + break; + case PCI_VENDOR_ID_INTEL: + ehci->need_io_watchdog = 0; + if (pdev->device == 0x0806 || pdev->device == 0x0811 + || pdev->device == 0x0829) { + ehci_info(ehci, "disable lpm for langwell/penwell\n"); + ehci->has_lpm = 0; + } + break; + case PCI_VENDOR_ID_NVIDIA: + switch (pdev->device) { + /* MCP89 chips on the MacBookAir3,1 give EPROTO when + * fetching device descriptors unless LPM is disabled. + * There are also intermittent problems enumerating + * devices with PPCD enabled. + */ + case 0x0d9d: + ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); + ehci->has_lpm = 0; + ehci->has_ppcd = 0; + ehci->command &= ~CMD_PPCEE; + break; + } + break; + } + /* optional debug port, normally in the first BAR */ temp = pci_find_capability(pdev, 0x0a); if (temp) { @@ -238,7 +237,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) temp >>= 16; if ((temp & (3 << 13)) == (1 << 13)) { temp &= 0x1fff; - ehci->debug = ehci_to_hcd(ehci)->regs + temp; + 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), @@ -250,8 +249,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } } - ehci_reset(ehci); - /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; @@ -275,10 +272,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } /* Serial Bus Release Number is at PCI 0x60 offset */ - pci_read_config_byte(pdev, 0x60, &ehci->sbrn); if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) - ehci->sbrn = 0x20; /* ConneXT has no sbrn register */ + ; /* ConneXT has no sbrn register */ + else + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); /* Keep this around for a while just in case some EHCI * implementation uses legacy PCI PM support. This test |