static void usb_xhci_init(struct device *dev) { struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0); u32 reg32; u16 reg16; config_t *config = dev->chip_info; /* D20:F0:74h[1:0] = 00b (set D0 state) */ reg16 = pci_read_config16(dev, XHCI_PWR_CTL_STS); reg16 &= ~PWR_CTL_SET_MASK; reg16 |= PWR_CTL_SET_D0; pci_write_config16(dev, XHCI_PWR_CTL_STS, reg16); /* Disable Compliance Mode Entry */ reg32 = read32(res2mmio(res, 0x80ec, 0)); reg32 |= (1 << 0); write32(res2mmio(res, 0x80ec, 0), reg32); /* Enable clock gating first */ usb_xhci_clock_gating(dev); if (acpi_is_wakeup_s3()) { /* Reset ports that are disabled or * polling before returning to the OS. */ usb_xhci_reset_usb3(dev, 0); } else if (config->xhci_default) { /* Route all ports to XHCI */ outb(0xca, 0xb2); } }
/* Handler for XHCI controller on entry to S3/S4/S5 */ void usb_xhci_sleep_prepare(pci_devfn_t dev, u8 slp_typ) { u16 reg16; u32 reg32; u8 *mem_base = usb_xhci_mem_base(dev); if (!mem_base || slp_typ < ACPI_S3) return; if (pch_is_lp()) { /* Set D0 state */ reg16 = pci_read_config16(dev, XHCI_PWR_CTL_STS); reg16 &= ~PWR_CTL_SET_MASK; reg16 |= PWR_CTL_SET_D0; pci_write_config16(dev, XHCI_PWR_CTL_STS, reg16); /* Clear PCI 0xB0[14:13] */ reg32 = pci_read_config32(dev, 0xb0); reg32 &= ~((1 << 14) | (1 << 13)); pci_write_config32(dev, 0xb0, reg32); /* Clear MMIO 0x816c[14,2] */ reg32 = read32(mem_base + 0x816c); reg32 &= ~((1 << 14) | (1 << 2)); write32(mem_base + 0x816c, reg32); /* Reset disconnected USB3 ports */ usb_xhci_reset_usb3(dev, 0); /* Set MMIO 0x80e0[15] */ reg32 = read32(mem_base + 0x80e0); reg32 |= (1 << 15); write32(mem_base + 0x80e0, reg32); } /* Set D3Hot state and enable PME */ pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_SET_D3); pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_STATUS_PME); pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_ENABLE_PME); }
/* Route all ports to XHCI controller */ void usb_xhci_route_all(void) { u32 port_mask, route; u16 reg16; /* Skip if EHCI is already disabled */ if (RCBA32(FD) & PCH_DISABLE_EHCI1) return; /* Set D0 state */ reg16 = pci_read_config16(PCH_XHCI_DEV, XHCI_PWR_CTL_STS); reg16 &= ~PWR_CTL_SET_MASK; reg16 |= PWR_CTL_SET_D0; pci_write_config16(PCH_XHCI_DEV, XHCI_PWR_CTL_STS, reg16); /* Set USB3 superspeed enable */ port_mask = pci_read_config32(PCH_XHCI_DEV, XHCI_USB3PRM); route = pci_read_config32(PCH_XHCI_DEV, XHCI_USB3PR); route &= ~XHCI_USB3PR_SSEN; route |= XHCI_USB3PR_SSEN & port_mask; pci_write_config32(PCH_XHCI_DEV, XHCI_USB3PR, route); /* Route USB2 ports to XHCI controller */ port_mask = pci_read_config32(PCH_XHCI_DEV, XHCI_USB2PRM); route = pci_read_config32(PCH_XHCI_DEV, XHCI_USB2PR); route &= ~XHCI_USB2PR_HCSEL; route |= XHCI_USB2PR_HCSEL & port_mask; pci_write_config32(PCH_XHCI_DEV, XHCI_USB2PR, route); /* Disable EHCI controller */ usb_ehci_disable(PCH_EHCI1_DEV); /* LynxPoint-H has a second EHCI controller */ if (!pch_is_lp()) usb_ehci_disable(PCH_EHCI2_DEV); /* Reset and clear port change status */ usb_xhci_reset_usb3(PCH_XHCI_DEV, 1); }
static void usb_xhci_init(device_t dev) { u32 reg32; u16 reg16; u32 mem_base = usb_xhci_mem_base(dev); config_t *config = dev->chip_info; /* D20:F0:74h[1:0] = 00b (set D0 state) */ reg16 = pci_read_config16(dev, XHCI_PWR_CTL_STS); reg16 &= ~PWR_CTL_SET_MASK; reg16 |= PWR_CTL_SET_D0; pci_write_config16(dev, XHCI_PWR_CTL_STS, reg16); /* Enable clock gating first */ usb_xhci_clock_gating(dev); reg32 = read32(mem_base + 0x8144); if (pch_is_lp()) { /* XHCIBAR + 8144h[8,7,6] = 111b */ reg32 |= (1 << 8) | (1 << 7) | (1 << 6); } else { /* XHCIBAR + 8144h[8,7,6] = 100b */ reg32 &= ~((1 << 7) | (1 << 6)); reg32 |= (1 << 8); } write32(mem_base + 0x8144, reg32); if (pch_is_lp()) { /* XHCIBAR + 816Ch[19:0] = 000e0038h */ reg32 = read32(mem_base + 0x816c); reg32 &= ~0x000fffff; reg32 |= 0x000e0038; write32(mem_base + 0x816c, reg32); /* D20:F0:B0h[17,14,13] = 100b */ reg32 = pci_read_config32(dev, 0xb0); reg32 &= ~((1 << 14) | (1 << 13)); reg32 |= (1 << 17); pci_write_config32(dev, 0xb0, reg32); } reg32 = pci_read_config32(dev, 0x50); if (pch_is_lp()) { /* D20:F0:50h[28:0] = 0FCE2E5Fh */ reg32 &= ~0x1fffffff; reg32 |= 0x0fce2e5f; } else { /* D20:F0:50h[26:0] = 07886E9Fh */ reg32 &= ~0x07ffffff; reg32 |= 0x07886e9f; } pci_write_config32(dev, 0x50, reg32); /* D20:F0:44h[31] = 1 (Access Control Bit) */ reg32 = pci_read_config32(dev, 0x44); reg32 |= (1 << 31); pci_write_config32(dev, 0x44, reg32); /* D20:F0:40h[31,23] = 10b (OC Configuration Done) */ reg32 = pci_read_config32(dev, 0x40); reg32 &= ~(1 << 23); /* unsupported request */ reg32 |= (1 << 31); pci_write_config32(dev, 0x40, reg32); #if CONFIG_HAVE_ACPI_RESUME if (acpi_slp_type == 3) { /* Reset ports that are disabled or * polling before returning to the OS. */ usb_xhci_reset_usb3(dev, 0); } else #endif /* Route all ports to XHCI */ if (config->xhci_default) outb(0xca, 0xb2); }