|
69 | 69 | #define NB_PIF0_PWRDOWN_0 0x01100012
|
70 | 70 | #define NB_PIF0_PWRDOWN_1 0x01100013
|
71 | 71 |
|
| 72 | +#define USB_INTEL_XUSB2PR 0xD0 |
| 73 | +#define USB_INTEL_USB3_PSSEN 0xD8 |
| 74 | + |
72 | 75 | static struct amd_chipset_info {
|
73 | 76 | struct pci_dev *nb_dev;
|
74 | 77 | struct pci_dev *smbus_dev;
|
@@ -673,6 +676,64 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
|
673 | 676 | return -ETIMEDOUT;
|
674 | 677 | }
|
675 | 678 |
|
| 679 | +bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) |
| 680 | +{ |
| 681 | + return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && |
| 682 | + pdev->vendor == PCI_VENDOR_ID_INTEL && |
| 683 | + pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI; |
| 684 | +} |
| 685 | +EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci); |
| 686 | + |
| 687 | +/* |
| 688 | + * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that |
| 689 | + * share some number of ports. These ports can be switched between either |
| 690 | + * controller. Not all of the ports under the EHCI host controller may be |
| 691 | + * switchable. |
| 692 | + * |
| 693 | + * The ports should be switched over to xHCI before PCI probes for any device |
| 694 | + * start. This avoids active devices under EHCI being disconnected during the |
| 695 | + * port switchover, which could cause loss of data on USB storage devices, or |
| 696 | + * failed boot when the root file system is on a USB mass storage device and is |
| 697 | + * enumerated under EHCI first. |
| 698 | + * |
| 699 | + * We write into the xHC's PCI configuration space in some Intel-specific |
| 700 | + * registers to switch the ports over. The USB 3.0 terminations and the USB |
| 701 | + * 2.0 data wires are switched separately. We want to enable the SuperSpeed |
| 702 | + * terminations before switching the USB 2.0 wires over, so that USB 3.0 |
| 703 | + * devices connect at SuperSpeed, rather than at USB 2.0 speeds. |
| 704 | + */ |
| 705 | +void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) |
| 706 | +{ |
| 707 | + u32 ports_available; |
| 708 | + |
| 709 | + ports_available = 0xffffffff; |
| 710 | + /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable |
| 711 | + * Register, to turn on SuperSpeed terminations for all |
| 712 | + * available ports. |
| 713 | + */ |
| 714 | + pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, |
| 715 | + cpu_to_le32(ports_available)); |
| 716 | + |
| 717 | + pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, |
| 718 | + &ports_available); |
| 719 | + dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " |
| 720 | + "under xHCI: 0x%x\n", ports_available); |
| 721 | + |
| 722 | + ports_available = 0xffffffff; |
| 723 | + /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to |
| 724 | + * switch the USB 2.0 power and data lines over to the xHCI |
| 725 | + * host. |
| 726 | + */ |
| 727 | + pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, |
| 728 | + cpu_to_le32(ports_available)); |
| 729 | + |
| 730 | + pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, |
| 731 | + &ports_available); |
| 732 | + dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over " |
| 733 | + "to xHCI: 0x%x\n", ports_available); |
| 734 | +} |
| 735 | +EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); |
| 736 | + |
676 | 737 | /**
|
677 | 738 | * PCI Quirks for xHCI.
|
678 | 739 | *
|
@@ -732,6 +793,8 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
|
732 | 793 | writel(XHCI_LEGACY_DISABLE_SMI,
|
733 | 794 | base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
|
734 | 795 |
|
| 796 | + if (usb_is_intel_switchable_xhci(pdev)) |
| 797 | + usb_enable_xhci_ports(pdev); |
735 | 798 | hc_init:
|
736 | 799 | op_reg_base = base + XHCI_HC_LENGTH(readl(base));
|
737 | 800 |
|
|
0 commit comments