#ifdefined(CONFIG_HAS_IOPORT) && IS_ENABLED(CONFIG_USB_UHCI_HCD) /* *Makesurethecontrolleriscompletelyinactive,unableto *generateinterruptsordoDMA.
*/ void uhci_reset_hc(struct pci_dev *pdev, unsignedlong base)
{ /* Turn off PIRQ enable and SMI enable. (This also turns off the *BIOS'sUSBLegacySupport.)TurnoffalltheR/WCbitstoo.
*/
pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
/* Reset the HC - this will force us to get a *newnotificationofanyalreadyconnected *portsduetothevirtualdisconnectthatit *implies.
*/
outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD);
mb();
udelay(5); if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
dev_warn(&pdev->dev, "HCRESET not completed yet!\n");
/* Just to be safe, disable interrupt requests and *makesurethecontrollerisstopped.
*/
outw(0, base + UHCI_USBINTR);
outw(0, base + UHCI_USBCMD);
}
EXPORT_SYMBOL_GPL(uhci_reset_hc);
/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ #ifdef __hppa__ #define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR) #else #define OHCI_CTRL_MASK OHCI_CTRL_RWC
if (control & OHCI_CTRL_IR) { int wait_time = 500; /* arbitrary; 5 seconds */
writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
writel(OHCI_OCR, base + OHCI_CMDSTATUS); while (wait_time > 0 &&
readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
wait_time -= 10;
msleep(10);
} if (wait_time <= 0)
dev_warn(&pdev->dev, "OHCI: BIOS handoff failed (BIOS bug?) %08x\n",
readl(base + OHCI_CONTROL));
} #endif
/* disable interrupts */
writel((u32) ~0, base + OHCI_INTRDISABLE);
/* Go into the USB_RESET state, preserving RWC (and possibly IR) */
writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
readl(base + OHCI_CONTROL);
/* software reset of the controller, preserving HcFmInterval */ if (!no_fminterval)
fminterval = readl(base + OHCI_FMINTERVAL);
writel(OHCI_HCR, base + OHCI_CMDSTATUS);
/* reset requires max 10 us delay */ for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) break;
udelay(1);
}
if (!no_fminterval)
writel(fminterval, base + OHCI_FMINTERVAL);
/* Now the controller is safely in SUSPEND and nothing can wake it up */
iounmap(base);
}
#if0 /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, *butthatseemsdubiousingeneral(theBIOSleftitoffintentionally) *andisknowntopreventsomesystemsfrombooting.sowewon'tdothis *unlessmaybewecandeterminewhenwe'reonasystemthatneedsSMIforced.
*/ /* BIOS workaround (?): be sure the pre-Linux code *receivestheSMI
*/
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 *setforanyotherreasonthanforcingaBIOS *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, *andhopenothinggoestoowrong
*/ 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 *anypowersessionstoremainintact.
*/ if (tried_handoff)
writel(0, op_reg_base + EHCI_CONFIGFLAG);
}
base = pci_ioremap_bar(pdev, 0); if (base == NULL) return;
cap_length = readb(base);
op_reg_base = base + cap_length;
/* EHCI 0.96 and later may have "extended capabilities" *specsection5.1explainsthebioshandoff,e.g.for *bootingfromUSBdiskorusingausbkeyboard
*/
hcc_params = readl(base + EHCI_HCC_PARAMS);
/* LS7A EHCI controller doesn't have extended capabilities, the *EECP(EHCIExtendedCapabilitiesPointer)fieldofHCCPARAMS *registershouldbe0x0butitreadsas0xa0.Soclearitto *avoiderrormessagesonboot.
*/ if (pdev->vendor == PCI_VENDOR_ID_LOONGSON && pdev->device == 0x7a14)
hcc_params &= ~(0xffL << 8);
/* Sony VAIO t-series with subsystem device ID 90a8 is not capable of *switchingportsfromEHCItoxHCI
*/ if (xhci_pdev->subsystem_vendor == PCI_VENDOR_ID_SONY &&
xhci_pdev->subsystem_device == 0x90a8) return;
/* make sure an intel EHCI controller exists */
for_each_pci_dev(companion) { if (companion->class == PCI_CLASS_SERIAL_USB_EHCI &&
companion->vendor == PCI_VENDOR_ID_INTEL) {
ehci_found = true; break;
}
}
if (!ehci_found) return;
/* Don't switchover the ports if the user hasn't compiled the xHCI *driver.Otherwisetheywillsee"dead"USBportsthatdon'tpower *thedevices.
*/ if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) {
dev_warn(&xhci_pdev->dev, "CONFIG_USB_XHCI_HCD is turned off, defaulting to EHCI.\n");
dev_warn(&xhci_pdev->dev, "USB 3.0 devices will work at USB 2.0 speeds.\n");
usb_disable_xhci_ports(xhci_pdev); return;
}
/* Read USB3PRM, the USB 3.0 Port Routing Mask Register *IndicatetheportsthatcanbechangedfromOS.
*/
pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM,
&ports_available);
dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n",
ports_available);
/* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable *Register,toturnonSuperSpeedterminationsforthe *switchableports.
*/
pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
ports_available);
pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
&ports_available);
dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled under xHCI: 0x%x\n",
ports_available);
/* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register *IndicatetheUSB2.0portstobecontrolledbythexHCIhost.
*/
dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n",
ports_available);
/* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to *switchtheUSB2.0poweranddatalinesovertothexHCI *host.
*/
pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
ports_available);
pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
&ports_available);
dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over to xHCI: 0x%x\n",
ports_available);
}
EXPORT_SYMBOL_GPL(usb_enable_intel_xhci_ports);
if ((ext_cap_offset + sizeof(val)) > len) { /* We're reading garbage from the controller */
dev_warn(&pdev->dev, "xHCI controller failing to respond"); goto iounmap;
}
val = readl(base + ext_cap_offset);
/* Auto handoff never worked for these devices. Force it and continue */ if ((pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241) ||
(pdev->vendor == PCI_VENDOR_ID_RENESAS
&& pdev->device == 0x0014)) {
val = (val | XHCI_HC_OS_OWNED) & ~XHCI_HC_BIOS_OWNED;
writel(val, base + ext_cap_offset);
}
/* If the BIOS owns the HC, signal that the OS wants it, and wait */ if (val & XHCI_HC_BIOS_OWNED) {
writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset);
/* Wait for 1 second with 10 microsecond polling interval */
timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, 0, 1000000, 10);
/* Assume a buggy BIOS and take HC ownership anyway */ if (timeout) {
dev_warn(&pdev->dev, "xHCI BIOS handoff failed (BIOS bug ?) %08x\n",
val);
writel(val & ~XHCI_HC_BIOS_OWNED, base + ext_cap_offset);
}
}
val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); /* Mask off (turn off) any enabled SMIs */
val &= XHCI_LEGACY_DISABLE_SMI; /* Mask all SMI events bits, RW1C */
val |= XHCI_LEGACY_SMI_EVENTS; /* Disable any BIOS SMIs and clear all SMI events*/
writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
hc_init: if (pdev->vendor == PCI_VENDOR_ID_INTEL)
usb_enable_intel_xhci_ports(pdev);
op_reg_base = base + XHCI_HC_LENGTH(readl(base));
/* Wait for the host controller to be ready before writing any *operationalorruntimeregisters.Wait5secondsandnomore.
*/
timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, 5000000, 10); /* Assume a buggy HC and start HC initialization anyway */ if (timeout) {
val = readl(op_reg_base + XHCI_STS_OFFSET);
dev_warn(&pdev->dev, "xHCI HW not ready after 5 sec (HC bug?) status = 0x%x\n",
val);
}
/* Send the halt and disable interrupts command */
val = readl(op_reg_base + XHCI_CMD_OFFSET);
val &= ~(XHCI_CMD_RUN | XHCI_IRQS);
writel(val, op_reg_base + XHCI_CMD_OFFSET);
/* Wait for the HC to halt - poll every 125 usec (one microframe). */
timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_HALT, 1,
XHCI_MAX_HALT_USEC, 125); if (timeout) {
val = readl(op_reg_base + XHCI_STS_OFFSET);
dev_warn(&pdev->dev, "xHCI HW did not halt within %d usec status = 0x%x\n",
XHCI_MAX_HALT_USEC, val);
}