ec: Add cros_ec support for ish variant

The Integrated Sensor Hub is a new EC type used on the Wilco platform.

BUG=b:130438917
TEST=mosys ish info on Sarien

Change-Id: Iae3b36e7b82c8f1322c69ba06eaa8215f1834d3c
Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1625452
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
diff --git a/core/command/ish.c b/core/command/ish.c
new file mode 100644
index 0000000..79654ad
--- /dev/null
+++ b/core/command/ish.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019, Google LLC.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of Google Inc. nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "mosys/kv_pair.h"
+#include "mosys/log.h"
+#include "mosys/platform.h"
+
+static int ish_info(struct platform_intf *intf, struct platform_cmd *cmd,
+		   int argc, char **argv)
+{
+	struct kv_pair *kv;
+	int rc;
+
+	if (!intf->cb->ish) {
+		errno = ENOSYS;
+		return -1;
+	}
+
+	kv = kv_pair_new();
+	if (!kv) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	if (!intf->cb->ish->vendor || !intf->cb->ish->name ||
+	    !intf->cb->ish->fw_version) {
+		errno = ENOSYS;
+		rc = -1;
+		goto ish_info_done;
+	}
+
+	kv_pair_add(kv, "vendor",
+			intf->cb->ish->vendor(intf, intf->cb->ish));
+	kv_pair_add(kv, "name", intf->cb->ish->name(intf, intf->cb->ish));
+	kv_pair_add(kv, "fw_version",
+			intf->cb->ish->fw_version(intf, intf->cb->ish));
+
+	rc = kv_pair_print(kv);
+
+ish_info_done:
+	kv_pair_free(kv);
+	return rc;
+}
+
+struct platform_cmd ish_cmds[] = {
+	{
+		.name	= "info",
+		.desc	= "Print basic EC information",
+		.type	= ARG_TYPE_GETTER,
+		.arg	= { .func = ish_info}
+	},
+	{ NULL }
+};
+
+struct platform_cmd cmd_ish = {
+	.name	= "ish",
+	.desc	= "ISH information",
+	.type	= ARG_TYPE_SUB,
+	.arg	= { .sub = ish_cmds }
+};
diff --git a/core/command/meson.build b/core/command/meson.build
index 2dfd270..9b5206e 100644
--- a/core/command/meson.build
+++ b/core/command/meson.build
@@ -17,5 +17,6 @@
   'psu.c',
   'platform.c',
   'ec.c',
+  'ish.c',
   'smbios.c',
 )
diff --git a/drivers/google/cros_ec.c b/drivers/google/cros_ec.c
index f0d7434..f48323c 100644
--- a/drivers/google/cros_ec.c
+++ b/drivers/google/cros_ec.c
@@ -450,3 +450,15 @@
 
 	return 0;
 }
+
+
+int cros_ish_setup(struct platform_intf *intf)
+{
+	MOSYS_CHECK(intf->cb && intf->cb->ish);
+
+	lprintf(LOG_DEBUG, "%s: Trying devfs interface...\n", __func__);
+	if (cros_ish_setup_dev(intf) == 1)
+		return 1;
+
+	return 0;
+}
diff --git a/drivers/google/cros_ec_cb.c b/drivers/google/cros_ec_cb.c
index e5ac09b..c52a9d3 100644
--- a/drivers/google/cros_ec_cb.c
+++ b/drivers/google/cros_ec_cb.c
@@ -84,8 +84,8 @@
 	return version;
 }
 
-__attribute__((unused)) static const char *
-cros_ec_build_info_cb(struct platform_intf *intf, struct ec_cb *ec)
+static const char *cros_ec_build_info_cb(struct platform_intf *intf,
+					 struct ec_cb *ec)
 {
 	static const char *build_info = NULL;
 
@@ -122,3 +122,9 @@
 	.name		= cros_ec_name,
 	.fw_version	= cros_ec_fw_version,
 };
+
+struct ec_cb cros_ish_cb = {
+	.vendor		= cros_ec_vendor,
+	.name		= cros_ec_name,
+	.fw_version	= cros_ec_build_info_cb,
+};
diff --git a/drivers/google/cros_ec_dev.c b/drivers/google/cros_ec_dev.c
index 36ed671..3ede339 100644
--- a/drivers/google/cros_ec_dev.c
+++ b/drivers/google/cros_ec_dev.c
@@ -417,3 +417,34 @@
 
 	return ret;
 }
+
+int cros_ish_setup_dev(struct platform_intf *intf)
+{
+	int ret;
+	static struct cros_ec_dev default_ish_dev = {
+		.name = CROS_ISH_DEV_NAME,
+	};
+	static struct cros_ec_priv default_ish_priv = {
+		.devfs = &default_ish_dev,
+	};
+
+	MOSYS_CHECK(intf->cb && intf->cb->ish);
+	if (!intf->cb->ish->priv) {
+		/*
+		 * Whoever ported the platform was lazy. Assume they want to
+		 * use the default CrOS ISH device.
+		 */
+		intf->cb->ish->priv = &default_ish_priv;
+		lprintf(LOG_DEBUG, "Using default ISH devfs interface.\n");
+	}
+
+	ret = cros_ec_probe_dev(intf, intf->cb->ish);
+	if (ret == 1)
+		lprintf(LOG_DEBUG, "CrOS ISH found via kernel driver\n");
+	else if (ret == 0)
+		lprintf(LOG_DEBUG, "CrOS ISH not found via kernel driver\n");
+	else
+		lprintf(LOG_ERR, "Error probing CrOS ISH via kernel driver\n");
+
+	return ret;
+}
diff --git a/include/drivers/google/cros_ec.h b/include/drivers/google/cros_ec.h
index 164c68a..ea45ace 100644
--- a/include/drivers/google/cros_ec.h
+++ b/include/drivers/google/cros_ec.h
@@ -42,6 +42,7 @@
 #define CROS_PD_DEV_NAME		"/dev/cros_pd"
 #define CROS_SH_DEV_NAME		"/dev/cros_sh"
 #define CROS_FP_DEV_NAME		"/dev/cros_fp"
+#define CROS_ISH_DEV_NAME		"/dev/cros_ish"
 
 struct eeprom;
 struct platform_intf;
@@ -86,6 +87,7 @@
 extern struct ec_cb cros_pd_cb;
 extern struct ec_cb cros_sh_cb;
 extern struct ec_cb cros_fp_cb;
+extern struct ec_cb cros_ish_cb;
 
 /* EC commands */
 int cros_ec_hello(struct platform_intf *intf, struct ec_cb *ec);
@@ -130,5 +132,6 @@
 int cros_ec_setup(struct platform_intf *intf);
 int cros_pd_setup(struct platform_intf *intf);
 int cros_fp_setup(struct platform_intf *intf);
+int cros_ish_setup(struct platform_intf *intf);
 
 #endif	/* MOSYS_DRIVERS_EC_GOOGLE__ */
diff --git a/include/drivers/google/cros_ec_dev.h b/include/drivers/google/cros_ec_dev.h
index bb5a9a6..02c8208 100644
--- a/include/drivers/google/cros_ec_dev.h
+++ b/include/drivers/google/cros_ec_dev.h
@@ -67,5 +67,6 @@
 extern int cros_ec_setup_dev(struct platform_intf *intf);
 extern int cros_pd_setup_dev(struct platform_intf *intf);
 extern int cros_fp_setup_dev(struct platform_intf *intf);
+extern int cros_ish_setup_dev(struct platform_intf *intf);
 
 #endif /* CROS_EC_DEV_H__ */
diff --git a/include/mosys/command_list.h b/include/mosys/command_list.h
index 7d4a2cc..db338d1 100644
--- a/include/mosys/command_list.h
+++ b/include/mosys/command_list.h
@@ -56,6 +56,7 @@
 extern struct platform_cmd cmd_sh;
 extern struct platform_cmd cmd_pd;
 extern struct platform_cmd cmd_fp;
+extern struct platform_cmd cmd_ish;
 extern struct platform_cmd cmd_battery;
 extern struct platform_cmd cmd_storage;
 extern struct platform_cmd cmd_psu;
diff --git a/include/mosys/platform.h b/include/mosys/platform.h
index 77d1a37..0b084ee 100644
--- a/include/mosys/platform.h
+++ b/include/mosys/platform.h
@@ -447,6 +447,7 @@
 	struct ec_cb *pd;		/* pd callbacks */
 	struct ec_cb *sh;		/* sh callbacks */
 	struct ec_cb *fp;		/* fp callbacks */
+	struct ec_cb *ish;		/* ish callbacks */
 	struct legacy_ec_cb *legacy_ec;	/* legacy ec callbacks */
 	struct hid_cb *hid;		/* hid callbacks */
 	struct battery_cb *battery;	/* battery callbacks */