baytrail: implement baytrail technical advisory 556192

This is the implementation of TA 556192
It's for errata USB Device May Not be Detected at System
Power-On
Please see more details in TA 556192

BUG=none
BRANCH=firmware-rambi-5216.B
TEST=boot ok on rambi. need more validation on it

Change-Id: I55dd6807a026b9d0d6595f65384bb0e7c9cad20c
Signed-off-by: Kane Chen <kane.chen@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/651811
Reviewed-by: YH Lin <yueherngl@chromium.org>
diff --git a/src/soc/intel/baytrail/baytrail/iosf.h b/src/soc/intel/baytrail/baytrail/iosf.h
index 9da86f5..c4ecc61 100644
--- a/src/soc/intel/baytrail/baytrail/iosf.h
+++ b/src/soc/intel/baytrail/baytrail/iosf.h
@@ -227,6 +227,9 @@
 # define DTR0_SPEED_1333	0x02
 # define DTR0_SPEED_1600	0x03
 
+#define PMSTS			0xc
+# define PMSTS_WRO_MASK		0x100
+# define PMSTS_DISR_MASK	0x0
 /*
  * PUNIT Registers
  */
diff --git a/src/soc/intel/baytrail/baytrail/ramstage.h b/src/soc/intel/baytrail/baytrail/ramstage.h
index a8b5fdc..c935d5a 100644
--- a/src/soc/intel/baytrail/baytrail/ramstage.h
+++ b/src/soc/intel/baytrail/baytrail/ramstage.h
@@ -36,6 +36,7 @@
 #endif
 void baytrail_init_scc(void);
 void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index);
+void byt_usb_wa(void);
 
 extern struct pci_operations soc_pci_ops;
 
diff --git a/src/soc/intel/baytrail/ehci.c b/src/soc/intel/baytrail/ehci.c
index d4e2986..0af66b6 100644
--- a/src/soc/intel/baytrail/ehci.c
+++ b/src/soc/intel/baytrail/ehci.c
@@ -31,6 +31,8 @@
 #include <baytrail/pmc.h>
 #include <baytrail/ramstage.h>
 #include <baytrail/ehci.h>
+#include <baytrail/xhci.h>
+#include <baytrail/iosf.h>
 
 #include "chip.h"
 
@@ -123,6 +125,83 @@
 	reg_script_run(usb2_phy_script);
 }
 
+void byt_usb_wa(void)
+{
+	u8 i;
+	u32 orig, per_port;
+
+	static const struct reg_script \
+		usb_workaround_script[BYTM_USB2_PORT_COUNT][8] = {
+		{
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4113, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4123, 0x7f13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4123, 0x13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4123, 0x4011),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4113, 0x108),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4113, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4113, 0x0),
+			REG_SCRIPT_END
+		},
+		{
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4213, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4223, 0x7f13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4223, 0x13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4223, 0x4011),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4213, 0x108),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4213, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4213, 0x0),
+			REG_SCRIPT_END
+		},
+		{
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4313, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4323, 0x7f13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4323, 0x13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4323, 0x4011),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4313, 0x108),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4313, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4313, 0x0),
+			REG_SCRIPT_END
+		},
+		{
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4413, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4423, 0x7f13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4423, 0x13),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4423, 0x4011),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4413, 0x108),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4413, 0x8),
+			REG_IOSF_WRITE(IOSF_PORT_USBPHY, 0x4413, 0x0),
+			REG_SCRIPT_END
+		}
+	};
+
+	if (acpi_slp_type == 3 || \
+		(iosf_dunit_read(PMSTS) & PMSTS_WRO_MASK) > 0) {
+		printk(BIOS_DEBUG, "warm reset/S3 resume detected \
+				  , skip USB WA \n");
+		return;
+	}
+
+	printk(BIOS_DEBUG, "Start USB WA for BYT\n");
+	for (i = 0; i < BYTM_USB2_PORT_COUNT; i++) {
+		/*
+		 * The below reg_script_run is for steps 1 ~ 7 in the Tech Advisory
+		 * for each port
+		 */
+		reg_script_run(usb_workaround_script[i]);
+
+		/*
+		 * The below programing is for steps 8 ~ 12 in the Tech Advisory
+		 * for each port
+		 */
+		per_port = 0x4126 + i * 0x100;
+		orig = iosf_usbphy_read(per_port);
+		iosf_usbphy_write(per_port, 0x1c);
+		iosf_usbphy_write(per_port, 0x0);
+		iosf_usbphy_write(per_port, 0x11c);
+		iosf_usbphy_write(per_port, orig);
+	}
+}
+
 static void ehci_init(device_t dev)
 {
 	struct soc_intel_baytrail_config *config = dev->chip_info;
diff --git a/src/soc/intel/baytrail/ramstage.c b/src/soc/intel/baytrail/ramstage.c
index fcaf41f..82c25f1 100644
--- a/src/soc/intel/baytrail/ramstage.c
+++ b/src/soc/intel/baytrail/ramstage.c
@@ -217,4 +217,7 @@
 	setup_soc_gpios(gpio_config, config->enable_xdp_tap);
 
 	baytrail_init_scc();
+
+	/* Execute Tech Advisory 556192 */
+	byt_usb_wa();
 }