diff --git a/Documentation/ABI/testing/sysfs-platform-wilco-ec b/Documentation/ABI/testing/sysfs-platform-wilco-ec
new file mode 100644
index 000000000000..fd2400844470
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-wilco-ec
@@ -0,0 +1,42 @@
+What:		/sys/bus/platform/devices/GOOG000C\:00/version_label
+Date:		January 2019
+KernelVersion:	4.19
+Description:
+		Display Wilco Embedded Controller firmware version label.
+		Output will a version string be similar to the example below:
+		95.00.06
+
+What:		/sys/bus/platform/devices/GOOG000C\:00/version_svn_revision
+Date:		January 2019
+KernelVersion:	4.19
+Description:
+		Display Wilco Embedded Controller SVN revision.
+		Output will a version string be similar to the example below:
+		5960a.06
+
+What:		/sys/bus/platform/devices/GOOG000C\:00/version_model_number
+Date:		January 2019
+KernelVersion:	4.19
+Description:
+		Display Wilco Embedded Controller model number.
+		Output will a version string be similar to the example below:
+		08;8
+
+What:		/sys/bus/platform/devices/GOOG000C\:00/version_build_date
+Date:		January 2019
+KernelVersion:	4.19
+Description:
+		Display Wilco Embedded Controller firmware build date.
+		Output will a MM/DD/YY string.
+
+What:		/sys/bus/platform/devices/GOOG000C\:00/stealth_mode
+Date:		January 2019
+KernelVersion:	4.19
+Description:
+		Turn stealth_mode on or off on EC. Stealth mode means that the
+		various LEDs, the LCD backlight, and onboard speakers are turned
+		off and remain off even if activated from the off state.
+		External monitors connected to the system are not affected.
+		In addition Wireless devices are turned off.
+
+		Input should be parseable by kstrtobool().
diff --git a/drivers/platform/chrome/wilco_ec/Makefile b/drivers/platform/chrome/wilco_ec/Makefile
index 063e7fb4ea17..b4dadf8b1a07 100644
--- a/drivers/platform/chrome/wilco_ec/Makefile
+++ b/drivers/platform/chrome/wilco_ec/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-wilco_ec-objs				:= core.o mailbox.o
+wilco_ec-objs				:= core.o mailbox.o sysfs.o legacy.o
 obj-$(CONFIG_WILCO_EC)			+= wilco_ec.o
 wilco_ec_debugfs-objs			:= debugfs.o
 obj-$(CONFIG_WILCO_EC_DEBUGFS)		+= wilco_ec_debugfs.o
diff --git a/drivers/platform/chrome/wilco_ec/core.c b/drivers/platform/chrome/wilco_ec/core.c
index 7cfb047e2c89..1a1cd8e59f3f 100644
--- a/drivers/platform/chrome/wilco_ec/core.c
+++ b/drivers/platform/chrome/wilco_ec/core.c
@@ -101,6 +101,13 @@ static int wilco_ec_probe(struct platform_device *pdev)
 		goto destroy_mec;
 	}
 
+	/* Create sysfs attributes for userspace interaction */
+	ret = wilco_ec_sysfs_init(ec);
+	if (ret) {
+		dev_err(dev, "Failed to create sysfs attributes\n");
+		goto destroy_mec;
+	}
+
 	return 0;
 
 destroy_mec:
@@ -110,6 +117,11 @@ static int wilco_ec_probe(struct platform_device *pdev)
 
 static int wilco_ec_remove(struct platform_device *pdev)
 {
+	struct wilco_ec_device *ec = platform_get_drvdata(pdev);
+
+	/* Remove sysfs attributes */
+	wilco_ec_sysfs_remove(ec);
+
 	/* Teardown cros_ec interface */
 	cros_ec_lpc_mec_destroy();
 
diff --git a/drivers/platform/chrome/wilco_ec/legacy.c b/drivers/platform/chrome/wilco_ec/legacy.c
new file mode 100644
index 000000000000..f284088e70f4
--- /dev/null
+++ b/drivers/platform/chrome/wilco_ec/legacy.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Legacy (non-Chrome-specific) sysfs attributes for Wilco EC
+ *
+ * Copyright 2018 Google LLC
+ */
+
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/platform_data/wilco-ec.h>
+
+#include "legacy.h"
+
+#define EC_COMMAND_EC_INFO		0x38
+#define EC_INFO_SIZE			9
+#define EC_COMMAND_STEALTH_MODE		0xfc
+
+#define VERSION_INDEX_LABEL		0
+#define VERSION_INDEX_SVN_REVISION	1
+#define VERSION_INDEX_MODEL_NUMBER	2
+#define VERSION_INDEX_BUILD_DATE	3
+
+static ssize_t get_info(struct device *dev, char *buf, u8 index)
+{
+	struct wilco_ec_device *ec = dev_get_drvdata(dev);
+	char result[EC_INFO_SIZE];
+	struct wilco_ec_message msg = {
+		.type = WILCO_EC_MSG_LEGACY,
+		.command = EC_COMMAND_EC_INFO,
+		.request_data = &index,
+		.request_size = sizeof(index),
+		.response_data = result,
+		.response_size = EC_INFO_SIZE,
+	};
+	int ret;
+
+	ret = wilco_ec_mailbox(ec, &msg);
+	if (ret < 0)
+		return ret;
+	if (ret != EC_INFO_SIZE)
+		return -EBADMSG;
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n", result);
+}
+
+ssize_t wilco_ec_version_label_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	return get_info(dev, buf, VERSION_INDEX_LABEL);
+}
+
+ssize_t wilco_ec_version_svn_revision_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	return get_info(dev, buf, VERSION_INDEX_SVN_REVISION);
+}
+
+ssize_t wilco_ec_version_model_number_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	return get_info(dev, buf, VERSION_INDEX_MODEL_NUMBER);
+}
+
+ssize_t wilco_ec_version_build_date_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return get_info(dev, buf, VERSION_INDEX_BUILD_DATE);
+}
+
+ssize_t wilco_ec_stealth_mode_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct wilco_ec_device *ec = dev_get_drvdata(dev);
+	u8 param;
+	struct wilco_ec_message msg = {
+		.type = WILCO_EC_MSG_LEGACY,
+		.command = EC_COMMAND_STEALTH_MODE,
+		.request_data = &param,
+		.request_size = sizeof(param),
+	};
+	int ret;
+	bool enable;
+
+	ret = kstrtobool(buf, &enable);
+	if (ret) {
+		dev_err(dev, "Unable to parse '%s' to bool", buf);
+		return ret;
+	}
+
+	/* Invert input parameter, EC expects 0=on and 1=off */
+	param = !enable;
+
+	ret = wilco_ec_mailbox(ec, &msg);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
diff --git a/drivers/platform/chrome/wilco_ec/legacy.h b/drivers/platform/chrome/wilco_ec/legacy.h
new file mode 100644
index 000000000000..a7f51dec4ccb
--- /dev/null
+++ b/drivers/platform/chrome/wilco_ec/legacy.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Legacy (non-Chrome-specific) sysfs attributes for Wilco EC
+ *
+ * Copyright 2018 Google LLC
+ */
+
+#ifndef WILCO_EC_LEGACY_H
+#define WILCO_EC_LEGACY_H
+
+#include <linux/device.h>
+
+/**
+ * wilco_ec_version_label_show() - Display Wilco EC version label
+ * @dev: The device underlying the struct wilco_ec_device
+ * @attr: The attribute being read from
+ * @buf: Output buffer to fill with the result
+ *
+ * Output will a version string be similar to the example below:
+ * 95.00.06
+ */
+ssize_t wilco_ec_version_label_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf);
+
+/**
+ * wilco_ec_version_svn_revision_show() - Display Wilco EC SVN revision
+ * @dev: The device underlying the struct wilco_ec_device
+ * @attr: The attribute being read from
+ * @buf: Output buffer to fill with the result
+ *
+ * Output will a version string be similar to the example below:
+ * 5960a.06
+ */
+ssize_t wilco_ec_version_svn_revision_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf);
+
+/**
+ * wilco_ec_version_model_number_show() - Display Wilco EC model number
+ * @dev: The device underlying the struct wilco_ec_device
+ * @attr: The attribute being read from
+ * @buf: Output buffer to fill with the result
+ *
+ * Output will a version string be similar to the example below:
+ * 08;8
+ */
+ssize_t wilco_ec_version_model_number_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf);
+
+/**
+ * wilco_ec_version_build_date_show() - Display Wilco EC firmware build date
+ * @dev: The device underlying the struct wilco_ec_device
+ * @attr: The attribute being read from
+ * @buf: Output buffer to fill with the result
+ *
+ * Output will a MM/DD/YY string.
+ */
+ssize_t wilco_ec_version_build_date_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf);
+
+
+/**
+ * wilco_ec_stealth_mode_store() - Turn stealth_mode on or off on EC
+ * @dev: Device representing the EC
+ * @attr: The attribute in question
+ * @buf: Input buffer, should be parseable by kstrtobool(). Anything parsed to
+ *	 True means enable stealth mode (turn off screen, etc)
+ * @count: Number of bytes in input buffer
+ *
+ * Return: Number of bytes consumed from input, negative error code on failure
+ */
+ssize_t wilco_ec_stealth_mode_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count);
+
+#endif /* WILCO_EC_LEGACY_H */
diff --git a/drivers/platform/chrome/wilco_ec/sysfs.c b/drivers/platform/chrome/wilco_ec/sysfs.c
new file mode 100644
index 000000000000..a885026e5d24
--- /dev/null
+++ b/drivers/platform/chrome/wilco_ec/sysfs.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sysfs attributes for Wilco Embedded Controller
+ *
+ * Copyright 2018 Google LLC
+ *
+ * The sysfs attributes appear under /sys/bus/platform/devices/GOOG000C\:00/
+ * To actually learn what each attribute does, read the corresponding _show() or
+ * _store() function source.
+ */
+
+#include <linux/ctype.h>
+#include <linux/platform_data/wilco-ec.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+
+#include "legacy.h"
+
+#define WILCO_EC_ATTR_RO(_name)						\
+__ATTR(_name, 0444, wilco_ec_##_name##_show, NULL)
+
+#define WILCO_EC_ATTR_WO(_name)						\
+__ATTR(_name, 0200, NULL, wilco_ec_##_name##_store)
+
+/* Make top-level attributes, which will live inside GOOG000C:00/ */
+static struct device_attribute stealth_attr = WILCO_EC_ATTR_WO(stealth_mode);
+static struct device_attribute version_label_attr =
+					WILCO_EC_ATTR_RO(version_label);
+static struct device_attribute version_svn_revision_attr =
+					WILCO_EC_ATTR_RO(version_svn_revision);
+static struct device_attribute version_model_number_attr =
+					WILCO_EC_ATTR_RO(version_model_number);
+static struct device_attribute version_build_date_attr =
+					WILCO_EC_ATTR_RO(version_build_date);
+static struct attribute *wilco_ec_toplevel_attrs[] = {
+	&version_label_attr.attr,
+	&version_svn_revision_attr.attr,
+	&version_model_number_attr.attr,
+	&version_build_date_attr.attr,
+	&stealth_attr.attr,
+	NULL
+};
+static const struct attribute_group wilco_ec_toplevel_group = {
+	.attrs = wilco_ec_toplevel_attrs,
+};
+static const struct attribute_group *wilco_ec_toplevel_groups[] = {
+	&wilco_ec_toplevel_group,
+	NULL,
+};
+
+/**
+ * wilco_ec_sysfs_init() - Initialize the sysfs directories and attributes
+ * @dev: The device representing the EC
+ *
+ * Creates the sysfs directory structure and populates it with all attributes.
+ * If there is a problem it will clean up the entire filesystem.
+ *
+ * Return 0 on success, -ENOMEM on failure creating directories or attibutes.
+ */
+int wilco_ec_sysfs_init(struct wilco_ec_device *ec)
+{
+	struct device *dev = ec->dev;
+	int ret;
+
+	/* add the top-level attributes */
+	ret = sysfs_create_groups(&dev->kobj, wilco_ec_toplevel_groups);
+	if (ret)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void wilco_ec_sysfs_remove(struct wilco_ec_device *ec)
+{
+	struct device *dev = ec->dev;
+
+	/* go upwards through the directory structure */
+	sysfs_remove_groups(&dev->kobj, wilco_ec_toplevel_groups);
+}
diff --git a/include/linux/platform_data/wilco-ec.h b/include/linux/platform_data/wilco-ec.h
index 5477b8802f81..7c6ab6de7239 100644
--- a/include/linux/platform_data/wilco-ec.h
+++ b/include/linux/platform_data/wilco-ec.h
@@ -135,4 +135,18 @@ struct wilco_ec_response {
  */
 int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg);
 
+/**
+ * wilco_ec_sysfs_init() - Create sysfs attributes.
+ * @ec: EC device.
+ *
+ * Return: 0 for success or negative error code on failure.
+ */
+int wilco_ec_sysfs_init(struct wilco_ec_device *ec);
+
+/**
+ * wilco_ec_sysfs_remove() - Remove sysfs attributes.
+ * @ec: EC device.
+ */
+void wilco_ec_sysfs_remove(struct wilco_ec_device *ec);
+
 #endif /* WILCO_EC_H */
