|
@@ -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
|