CHERRY-PICK: Stout: Fall back to ACPI ports on version read failure.

Sideband ports are not implemented in RO mode on Stout. It creates
problems when trying to read the EC version. Therefore, if version read
fails, assume we are in recovery and attempt to use the regular ACPI ports.

TEST=Manual. "mosys ec info" in recovery / RO mode.
BUG=chrome-os-partner:18004.
BRANCH=Stout.

Change-Id: I7e64694ee8dab68fb6690e5c53700b9b5569db35
Original-Change-Id: Iebcf024b9b64823fafefa03a9293a8b1ee9f1188
Reviewed-on: https://gerrit.chromium.org/gerrit/44010
Commit-Queue: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-by: Shawn Nematbakhsh <shawnn@chromium.org>
Tested-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/44253
diff --git a/platform/lenovo/stout/battery.c b/platform/lenovo/stout/battery.c
index de16419..2fe6f46 100644
--- a/platform/lenovo/stout/battery.c
+++ b/platform/lenovo/stout/battery.c
@@ -70,7 +70,8 @@
 	uint8_t status, date_hi, date_lo;
 	int day, month, year;
 
-	if (ecram_read(intf, STOUT_ECMEM_BATTERY_STATUS, &status) < 0)
+	if (ecram_read(intf, STOUT_ECMEM_BATTERY_STATUS, &status,
+	               STOUT_ECCMD_MEM_READ) < 0)
 		return NULL;
 
 	/* Bit 7: main battery attached. */
@@ -121,7 +122,8 @@
 		return -1;
 	}
 
-	if (ecram_read(intf, STOUT_ECMEM_BATTERY_STATUS, &status) < 0)
+	if (ecram_read(intf, STOUT_ECMEM_BATTERY_STATUS, &status,
+	               STOUT_ECCMD_MEM_READ) < 0)
 		return -1;
 
 	/* Bit 7: main battery attached. */
@@ -177,8 +179,9 @@
 static int stout_update_battery_fw(struct platform_intf *intf)
 {
 	uint8_t status;
+	stout_ec_command cmd = STOUT_ECCMD_MEM_READ;
 
-	if (ecram_read(intf, STOUT_ECMEM_BATTERY_STATUS, &status) < 0)
+	if (ecram_read(intf, STOUT_ECMEM_BATTERY_STATUS, &status, cmd) < 0)
 		return -1;
 
 	/* Bit 7: main battery attached. */
@@ -199,7 +202,7 @@
 	}
 
 	/* Start update. */
-	if (ecram_read(intf, STOUT_ECMEM_BATTERY_FW_UPDATE, &status) < 0)
+	if (ecram_read(intf, STOUT_ECMEM_BATTERY_FW_UPDATE, &status, cmd) < 0)
 		return -1;
 
 	lprintf(LOG_DEBUG, "%s: Starting FW update: %x.\n",
@@ -224,7 +227,7 @@
 		__func__, status);
 
 	/* Clear update flag and check competion status. */
-	if (ecram_read(intf, STOUT_ECMEM_BATTERY_FW_UPDATE, &status) < 0)
+	if (ecram_read(intf, STOUT_ECMEM_BATTERY_FW_UPDATE, &status, cmd) < 0)
 		return -1;
 
 	if (ecram_write(intf, STOUT_ECMEM_BATTERY_FW_UPDATE,
diff --git a/platform/lenovo/stout/ec.c b/platform/lenovo/stout/ec.c
index 2bd463e..bfc84fc 100644
--- a/platform/lenovo/stout/ec.c
+++ b/platform/lenovo/stout/ec.c
@@ -43,22 +43,30 @@
 
 #define STOUT_EC_CMD_TIMEOUT_MS		3000
 
-/* for i8042-style wait commands */
-static struct i8042_host_intf stout_acpi_intf = {
+static struct i8042_host_intf stout_acpi_intf_rw = {
 	/* use sideband ports to avoid racing with kernel ACPI driver */
 	.csr	= 0x6c,
 	.data	= 0x68,
 };
 
+static struct i8042_host_intf stout_acpi_intf_ro = {
+	/* try regular ports in case EC is in RO */
+	.csr	= ACPI_EC_SC,
+	.data	= ACPI_EC_DATA,
+};
+
+/* for i8042-style wait commands */
+static struct i8042_host_intf *stout_acpi_intf = &stout_acpi_intf_rw;
+
 static int stout_wait_ibf_clear(struct platform_intf *intf)
 {
-	return i8042_wait_ibf_clear(intf, &stout_acpi_intf,
+	return i8042_wait_ibf_clear(intf, stout_acpi_intf,
 			STOUT_EC_CMD_TIMEOUT_MS);
 }
 
 static int stout_wait_obf_set(struct platform_intf *intf)
 {
-	return i8042_wait_obf_set(intf, &stout_acpi_intf,
+	return i8042_wait_obf_set(intf, stout_acpi_intf,
 			STOUT_EC_CMD_TIMEOUT_MS);
 }
 
@@ -82,14 +90,14 @@
 
 	if (stout_wait_ibf_clear(intf) != 1)
 		return -1;
-	if (io_write8(intf, stout_acpi_intf.csr, command) < 0)
+	if (io_write8(intf, stout_acpi_intf->csr, command) < 0)
 		return -1;
 
 	if (input_data != NULL) {
 		for (i = 0; i < input_len; i++) {
 			if (stout_wait_ibf_clear(intf) != 1)
 				return -1;
-			if (io_write8(intf, stout_acpi_intf.data,
+			if (io_write8(intf, stout_acpi_intf->data,
 					input_data[i] ) < 0)
 				return -1;
 		}
@@ -99,7 +107,7 @@
 		for (i = 0; i < output_len; i++) {
 			if (stout_wait_obf_set(intf) != 1)
 				return -1;
-			if (io_read8(intf, stout_acpi_intf.data,
+			if (io_read8(intf, stout_acpi_intf->data,
 					&output_data[i] ) < 0)
 				return -1;
 		}
@@ -111,9 +119,10 @@
 
 /* returns 0 to indicate success, <0 to indicate failure */
 int ecram_read(struct platform_intf *intf,
-			stout_ec_mem_addr address, uint8_t *data)
+			stout_ec_mem_addr address, uint8_t *data,
+			stout_ec_command cmd)
 {
-	return ec_command(intf, STOUT_ECCMD_MEM_READ, (int8_t *)&address, 1,
+	return ec_command(intf, cmd, (int8_t *)&address, 1,
 				data, 1);
 }
 
@@ -141,10 +150,18 @@
 	char revision;
 	static char version[7];
 	uint8_t msb, lsb;
+	stout_ec_command cmd = STOUT_ECCMD_MEM_READ;
 
-	if (ecram_read(intf, STOUT_ECMEM_FW_VERSION_MSB, &msb) < 0)
-		return NULL;
-	if (ecram_read(intf, STOUT_ECMEM_FW_VERSION_LSB, &lsb) < 0)
+	if (ecram_read(intf, STOUT_ECMEM_FW_VERSION_MSB, &msb, cmd) < 0) {
+		/* Command failed, but we might be in RO. */
+		stout_acpi_intf = &stout_acpi_intf_ro;
+		cmd = ACPI_RD_EC;
+		lprintf(LOG_DEBUG, "%s: Retry w/ RO ports\n", __func__);
+
+		if (ecram_read(intf, STOUT_ECMEM_FW_VERSION_MSB, &msb, cmd) < 0)
+			return NULL;
+	}
+	if (ecram_read(intf, STOUT_ECMEM_FW_VERSION_LSB, &lsb, cmd) < 0)
 		return NULL;
 
 	major = (msb >> 4) & 0xf;
diff --git a/platform/lenovo/stout/stout.h b/platform/lenovo/stout/stout.h
index 31844eb..80d30f6 100644
--- a/platform/lenovo/stout/stout.h
+++ b/platform/lenovo/stout/stout.h
@@ -77,7 +77,8 @@
                         uint8_t *input_data, uint8_t input_len,
                         uint8_t *output_data, uint8_t output_len );
 extern int ecram_read(struct platform_intf *intf,
-                        stout_ec_mem_addr address, uint8_t *data);
+                        stout_ec_mem_addr address, uint8_t *data,
+			stout_ec_command cmd);
 extern int ecram_write(struct platform_intf *intf,
                         stout_ec_mem_addr address, uint8_t data);