diff options
author | Duncan Laurie <dlaurie@chromium.org> | 2013-09-25 14:08:16 -0700 |
---|---|---|
committer | Patrick Georgi <patrick@georgi-clan.de> | 2014-07-11 18:08:02 +0200 |
commit | 16a0f5c4e3677ce93949bb5383ebd04a636d13e7 (patch) | |
tree | cc0b5d3ef9228f19c47a0b876c9396b8d3f09c56 /src/southbridge | |
parent | 7fc2da910766686d55d489d0e539a1586b98d5bb (diff) |
intel/lynxpoint: xhci: Revert suspend/resume changes
I have been attempting to work around USB3 issues that appear in the
kernel with hacks in the firmware, but this is resulting in more
headaches in the kernel.
Instead remove all the work that was being done at resume time and undo
the change that was issuing a warm reset to all ports at suspend time.
The bad device behavior will be dealt with at the kernel level to
handle devices that get stuck in polling state after enable/disable
sequence.
BUG=chrome-os-partner:22754
BRANCH=falco,peppy,wolf,leon
TEST=manual:
suspend/resume with several misbehaving devices:
Kingston USB3 Media Reader
Transcend USB3 Media Reader
Various ADATA USB3 drives
Various Kingston USB3 sticks
Original-Change-Id: I0894454af42d2ced456fe0da921d74c9e74902d0
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/170107
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
(cherry picked from commit c2abb4d0dad6ed00e1e230d604c4c0a76eb4eef7)
Change-Id: Ib215d9c230f90a1c9f34bf29254bb9feec28c67e
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/170578
[pm: rebase to master branch of coreboot upstream]
Signed-off-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-on: http://review.coreboot.org/6016
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'src/southbridge')
-rw-r--r-- | src/southbridge/intel/lynxpoint/usb_xhci.c | 94 |
1 files changed, 9 insertions, 85 deletions
diff --git a/src/southbridge/intel/lynxpoint/usb_xhci.c b/src/southbridge/intel/lynxpoint/usb_xhci.c index f6409b4381..e09134081c 100644 --- a/src/southbridge/intel/lynxpoint/usb_xhci.c +++ b/src/southbridge/intel/lynxpoint/usb_xhci.c @@ -37,6 +37,8 @@ static u32 usb_xhci_mem_base(device_t dev) return mem_base & ~0xf; } +#ifdef __SMM__ + static int usb_xhci_port_count_usb3(device_t dev) { if (pch_is_lp()) { @@ -78,8 +80,6 @@ static void usb_xhci_reset_port_usb3(u32 mem_base, int port) #define XHCI_RESET_DELAY_US 1000 /* 1ms */ #define XHCI_RESET_TIMEOUT 100 /* 100ms */ -#ifdef __SMM__ - /* * 1) Wait until port is done polling * 2) If port is disconnected @@ -87,7 +87,7 @@ static void usb_xhci_reset_port_usb3(u32 mem_base, int port) * b) Poll for warm reset complete * c) Write 1 to port change status bits */ -static void usb_xhci_reset_usb3(device_t dev) +static void usb_xhci_reset_usb3(device_t dev, int all) { u32 status, port_disabled; int timeout, port; @@ -127,7 +127,10 @@ static void usb_xhci_reset_usb3(device_t dev) continue; status = read32(portsc) & XHCI_USB3_PORTSC_PLS; /* Reset all or only disconnected ports */ - usb_xhci_reset_port_usb3(mem_base, port); + if (all || status == XHCI_PLSR_RXDETECT) + usb_xhci_reset_port_usb3(mem_base, port); + else + port_disabled |= 1 << port; } /* Wait for warm reset complete on all reset ports */ @@ -181,7 +184,7 @@ void usb_xhci_sleep_prepare(device_t dev, u8 slp_typ) write32(mem_base + 0x816c, reg32); /* Reset disconnected USB3 ports */ - usb_xhci_reset_usb3(dev); + usb_xhci_reset_usb3(dev, 0); /* Set MMIO 0x80e0[15] */ reg32 = read32(mem_base + 0x80e0); @@ -233,7 +236,7 @@ void usb_xhci_route_all(void) usb_ehci_disable(PCH_EHCI2_DEV); /* Reset and clear port change status */ - usb_xhci_reset_usb3(PCH_XHCI_DEV); + usb_xhci_reset_usb3(PCH_XHCI_DEV, 1); } #else /* !__SMM__ */ @@ -285,81 +288,6 @@ static void usb_xhci_clock_gating(device_t dev) pci_write_config32(dev, 0xa4, reg32); } -/* Re-enable ports that are disabled */ -static void usb_xhci_enable_ports_usb3(device_t dev) -{ -#if CONFIG_FINALIZE_USB_ROUTE_XHCI - int port; - u32 portsc, status, disabled; - u32 mem_base = usb_xhci_mem_base(dev); - int port_count = usb_xhci_port_count_usb3(dev); - u8 port_reset = 0; - int timeout; - - if (!mem_base || !port_count) - return; - - /* Get port disable override map */ - disabled = pci_read_config32(dev, XHCI_USB3PDO); - - for (port = 0; port < port_count; port++) { - /* Skip overridden ports */ - if (disabled & (1 << port)) - continue; - portsc = mem_base + XHCI_USB3_PORTSC(port); - status = read32(portsc) & XHCI_USB3_PORTSC_PLS; - switch (status) { - case XHCI_PLSR_RXDETECT: - /* Clear change status */ - printk(BIOS_DEBUG, "usb_xhci reset status %d\n", port); - usb_xhci_reset_status_usb3(mem_base, port); - break; - case XHCI_PLSR_DISABLED: - default: - /* Reset port */ - printk(BIOS_DEBUG, "usb_xhci reset port %d\n", port); - usb_xhci_reset_port_usb3(mem_base, port); - port_reset |= 1 << port; - break; - } - } - - if (!port_reset) - return; - - /* Wait for warm reset complete on all reset ports */ - for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) { - int complete = 1; - for (port = 0; port < port_count; port++) { - /* Only check ports that were reset */ - if (!(port_reset & (1 << port))) - continue; - /* Check if warm reset is complete */ - status = read32(mem_base + XHCI_USB3_PORTSC(port)); - if (!(status & XHCI_USB3_PORTSC_WRC)) - complete = 0; - } - /* Check for warm reset complete in any port */ - if (complete) - break; - udelay(XHCI_RESET_DELAY_US); - } - - /* Enable ports that were reset */ - for (port = 0; port < port_count; port++) { - /* Only check ports that were reset */ - if (!(port_reset & (1 << port))) - continue; - /* Transition to enabled */ - portsc = mem_base + XHCI_USB3_PORTSC(port); - status = read32(portsc); - status &= ~(XHCI_USB3_PORTSC_PLS | XHCI_USB3_PORTSC_PED); - status |= XHCI_PLSW_ENABLE | XHCI_USB3_PORTSC_LWS; - write32(portsc, status); - } -#endif -} - static void usb_xhci_init(device_t dev) { u32 reg32; @@ -422,10 +350,6 @@ static void usb_xhci_init(device_t dev) reg32 &= ~(1 << 23); /* unsupported request */ reg32 |= (1 << 31); pci_write_config32(dev, 0x40, reg32); - - /* Enable ports that are disabled before returning to OS */ - if (acpi_is_wakeup_s3()) - usb_xhci_enable_ports_usb3(dev); } static void usb_xhci_set_subsystem(device_t dev, unsigned vendor, |