intel/skylake: Add support to enable wake-on-usb attach/detach

Three things are required to enable wake-on-usb:
1. 5V to USB ports should be enabled in S3.
2. ASL file needs to have appropriate wake bit set.
3. XHCI controller should have the wake on attach/detach bit set for the
corresponding port in PORTSCN register.

Only part missing was #3.

This CL adds support to allow mainboard to define a bitmap in
devicetree corresponding to the ports that it wants to enable
wake-on-usb feature. Based on the bitmap, wake on attach/detach bits in
PORTSCN would be set by xhci.asl for the appropriate ports.

BUG=chrome-os-partner:58734
BRANCH=None
TEST=Verified that with port 5 enabled, chell wakes up from S3 on usb
attach/detach.

Change-Id: I40a22a450e52f74a0ab93ebb8170555d834ebdaf
Signed-off-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: https://review.coreboot.org/17056
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/soc/intel/skylake/acpi/xhci.asl b/src/soc/intel/skylake/acpi/xhci.asl
index 1a1c6e3..96f3b6a 100644
--- a/src/soc/intel/skylake/acpi/xhci.asl
+++ b/src/soc/intel/skylake/acpi/xhci.asl
@@ -15,6 +15,55 @@
  * GNU General Public License for more details.
  */
 
+/*
+ * USB Port Wake Enable (UPWE) on usb attach/detach
+ * Arg0 - Port Number
+ * Arg1 - Port 1 Status and control offset
+ * Arg2 - xHCI Memory-mapped address
+ */
+Method (UPWE, 3, Serialized)
+{
+	/* Local0 = Arg1 + ((Arg0 - 1) * 0x10) */
+	Add (Arg1, Multiply (Subtract (Arg0, 1), 0x10), Local0)
+
+	/* Map ((XMEM << 16) + Local0 in PSCR */
+	OperationRegion (PSCR, SystemMemory,
+			 Add (ShiftLeft (Arg2, 16), Local0), 0x10)
+	Field (PSCR, AnyAcc, NoLock, Preserve)
+	{
+		, 25,
+		UPCE, 1,
+		UPDE, 1,
+	}
+	Store (One, UPCE)
+	Store (One, UPDE)
+}
+
+/*
+ * USB Wake Enable Setup (UWES)
+ * Arg0 - Port enable bitmap
+ * Arg1 - Port 1 Status and control offset
+ * Arg2 - xHCI Memory-mapped address
+ */
+Method (UWES, 3, Serialized)
+{
+	Store (Arg0, Local0)
+
+	While (One) {
+		FindSetRightBit (Local0, Local1)
+		If (LEqual (Local1, Zero)) {
+			Break
+		}
+		UPWE (Local1, Arg1, Arg2)
+		/*
+		 * Clear the lowest set bit in Local0 since it was
+		 * processed.
+		 * Local0 = Local0 & (Local0 - 1)
+		 */
+		And (Local0, Subtract (Local0, 1), Local0)
+	}
+}
+
 /* XHCI Controller 0:14.0 */
 
 Device (XHCI)
@@ -26,6 +75,8 @@
 	Method (_DSW, 3)
 	{
 		Store (Arg0, PMEE)
+		UWES (And (\U2WE, 0x3FF), 0x480, XMEM)
+		UWES (And (\U3WE, 0x3F), 0x540, XMEM)
 	}
 
 	Name (_S3D, 3)	/* D3 supported in S3 */