[coreboot-gerrit] Patch set updated for coreboot: f133f46 intel/lynxpoint: xhci: Port reset changes on suspend/resume

Paul Menzel (paulepanter@users.sourceforge.net) gerrit at coreboot.org
Mon Jun 16 16:29:35 CEST 2014


Paul Menzel (paulepanter at users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/6015

-gerrit

commit f133f4663b1ae46a37325a995197351c8b0a42b0
Author: Duncan Laurie <dlaurie at chromium.org>
Date:   Mon Sep 16 13:51:08 2013 -0700

    intel/lynxpoint: xhci: Port reset changes on suspend/resume
    
    Some USB3 devices are not showing up after suspend/resume cycles.
    In particular if a device uses a lower power state like U2 it may
    take longer to come up and the firmware needs to wait after sending
    a warm port reset.
    
    In addition skipping port reset to connected ports in the way into
    suspend was causing problems so instead send all ports a reset
    before suspend.
    
    BUG=chrome-os-partner:22402
    BRANCH=falco,peppy,leon,wolf
    TEST=manual:
    
    Suspend/resume with ADATA HE720 HDD (and other devices) both
    connected at suspend and connecting while in suspend and ensure
    that the devices always show up in the kernel.
    
    Change-Id: Ib7b15dc65792742b4ceb7dcfc4b2c83192eafcc2
    Signed-off-by: Duncan Laurie <dlaurie at chromium.org>
    Reviewed-on: https://chromium-review.googlesource.com/169548
    Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
 src/southbridge/intel/lynxpoint/usb_xhci.c | 63 ++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 17 deletions(-)

diff --git a/src/southbridge/intel/lynxpoint/usb_xhci.c b/src/southbridge/intel/lynxpoint/usb_xhci.c
index 23016fb..a8849c9 100644
--- a/src/southbridge/intel/lynxpoint/usb_xhci.c
+++ b/src/southbridge/intel/lynxpoint/usb_xhci.c
@@ -75,11 +75,11 @@ static void usb_xhci_reset_port_usb3(u32 mem_base, int port)
 	write32(portsc, read32(portsc) | XHCI_USB3_PORTSC_WPR);
 }
 
-#ifdef __SMM__
-
 #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, int all)
+static void usb_xhci_reset_usb3(device_t dev)
 {
 	u32 status, port_disabled;
 	int timeout, port;
@@ -127,10 +127,7 @@ static void usb_xhci_reset_usb3(device_t dev, int all)
 			continue;
 		status = read32(portsc) & XHCI_USB3_PORTSC_PLS;
 		/* Reset all or only disconnected ports */
-		if (all || status == XHCI_PLSR_RXDETECT)
-			usb_xhci_reset_port_usb3(mem_base, port);
-		else
-			port_disabled |= 1 << port; /* No reset */
+		usb_xhci_reset_port_usb3(mem_base, port);
 	}
 
 	/* Wait for warm reset complete on all reset ports */
@@ -184,7 +181,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, 0);
+		usb_xhci_reset_usb3(dev);
 
 		/* Set MMIO 0x80e0[15] */
 		reg32 = read32(mem_base + 0x80e0);
@@ -236,7 +233,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, 1);
+	usb_xhci_reset_usb3(PCH_XHCI_DEV);
 }
 
 #else /* !__SMM__ */
@@ -296,6 +293,8 @@ static void usb_xhci_enable_ports_usb3(device_t dev)
 	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;
@@ -309,25 +308,55 @@ static void usb_xhci_enable_ports_usb3(device_t dev)
 			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 port %d\n", port);
+			printk(BIOS_DEBUG, "usb_xhci reset status %d\n", port);
 			usb_xhci_reset_status_usb3(mem_base, port);
 			break;
 		case XHCI_PLSR_DISABLED:
 		default:
-			/* Transition to enabled */
-			printk(BIOS_DEBUG, "usb_xhci enable port %d\n", port);
+			/* Reset port */
+			printk(BIOS_DEBUG, "usb_xhci reset port %d\n", port);
 			usb_xhci_reset_port_usb3(mem_base, port);
-			status = read32(portsc);
-			status &= ~XHCI_USB3_PORTSC_PLS;
-			status |= XHCI_PLSW_ENABLE | XHCI_USB3_PORTSC_LWS;
-			write32(portsc, status);
+			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
 }
 



More information about the coreboot-gerrit mailing list