Commit 7b3d4f44 authored by Nick Crews's avatar Nick Crews Committed by Enric Balletbo i Serra
Browse files

platform/chrome: Add new driver for Wilco EC



This EC is an incompatible variant of the typical Chrome OS embedded
controller.  It uses the same low-level communication and a similar
protocol with some significant differences.  The EC firmware does
not support the same mailbox commands so it is not registered as a
cros_ec device type.  This commit exports the wilco_ec_mailbox()
function so that other modules can use it to communicate with the EC.

Signed-off-by: default avatarDuncan Laurie <dlaurie@google.com>
Signed-off-by: default avatarNick Crews <ncrews@chromium.org>
[Fix the sparse warning: symbol 'wilco_ec_transfer' was not declared]
Signed-off-by: default avatarWei Yongjun <weiyongjun1@huawei.com>
[Fix Kconfig dependencies for wilco_ec]
Reported-by: default avatarRandy Dunlap <rdunlap@infradead.org>
Signed-off-by: default avatarEnric Balletbo i Serra <enric.balletbo@collabora.com>
parent 6b7cb222
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -152,4 +152,6 @@ config CROS_EC_SYSFS
	  To compile this driver as a module, choose M here: the
	  module will be called cros_ec_sysfs.

source "drivers/platform/chrome/wilco_ec/Kconfig"

endif # CHROMEOS_PLATFORMS
+2 −0
Original line number Diff line number Diff line
@@ -14,3 +14,5 @@ obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
obj-$(CONFIG_CROS_EC_VBC)		+= cros_ec_vbc.o
obj-$(CONFIG_CROS_EC_DEBUGFS)		+= cros_ec_debugfs.o
obj-$(CONFIG_CROS_EC_SYSFS)		+= cros_ec_sysfs.o

obj-$(CONFIG_WILCO_EC)			+= wilco_ec/
+10 −0
Original line number Diff line number Diff line
config WILCO_EC
	tristate "ChromeOS Wilco Embedded Controller"
	depends on ACPI && X86 && CROS_EC_LPC_MEC
	help
	  If you say Y here, you get support for talking to the ChromeOS
	  Wilco EC over an eSPI bus. This uses a simple byte-level protocol
	  with a checksum.

	  To compile this driver as a module, choose M here: the
	  module will be called wilco_ec.
+4 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0

wilco_ec-objs				:= core.o mailbox.o
obj-$(CONFIG_WILCO_EC)			+= wilco_ec.o
+104 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Core driver for Wilco Embedded Controller
 *
 * Copyright 2018 Google LLC
 *
 * This is the entry point for the drivers that control the Wilco EC.
 * This driver is responsible for several tasks:
 * - Initialize the register interface that is used by wilco_ec_mailbox()
 * - Create a platform device which is picked up by the debugfs driver
 * - Create a platform device which is picked up by the RTC driver
 */

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/platform_data/wilco-ec.h>
#include <linux/platform_device.h>

#include "../cros_ec_lpc_mec.h"

#define DRV_NAME "wilco-ec"

static struct resource *wilco_get_resource(struct platform_device *pdev,
					   int index)
{
	struct device *dev = &pdev->dev;
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_IO, index);
	if (!res) {
		dev_dbg(dev, "Couldn't find IO resource %d\n", index);
		return res;
	}

	return devm_request_region(dev, res->start, resource_size(res),
				   dev_name(dev));
}

static int wilco_ec_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct wilco_ec_device *ec;

	ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
	if (!ec)
		return -ENOMEM;

	platform_set_drvdata(pdev, ec);
	ec->dev = dev;
	mutex_init(&ec->mailbox_lock);

	/* Largest data buffer size requirement is extended data response */
	ec->data_size = sizeof(struct wilco_ec_response) +
		EC_MAILBOX_DATA_SIZE_EXTENDED;
	ec->data_buffer = devm_kzalloc(dev, ec->data_size, GFP_KERNEL);
	if (!ec->data_buffer)
		return -ENOMEM;

	/* Prepare access to IO regions provided by ACPI */
	ec->io_data = wilco_get_resource(pdev, 0);	/* Host Data */
	ec->io_command = wilco_get_resource(pdev, 1);	/* Host Command */
	ec->io_packet = wilco_get_resource(pdev, 2);	/* MEC EMI */
	if (!ec->io_data || !ec->io_command || !ec->io_packet)
		return -ENODEV;

	/* Initialize cros_ec register interface for communication */
	cros_ec_lpc_mec_init(ec->io_packet->start,
			     ec->io_packet->start + EC_MAILBOX_DATA_SIZE);

	return 0;
}

static int wilco_ec_remove(struct platform_device *pdev)
{
	/* Teardown cros_ec interface */
	cros_ec_lpc_mec_destroy();

	return 0;
}

static const struct acpi_device_id wilco_ec_acpi_device_ids[] = {
	{ "GOOG000C", 0 },
	{ }
};
MODULE_DEVICE_TABLE(acpi, wilco_ec_acpi_device_ids);

static struct platform_driver wilco_ec_driver = {
	.driver = {
		.name = DRV_NAME,
		.acpi_match_table = wilco_ec_acpi_device_ids,
	},
	.probe = wilco_ec_probe,
	.remove = wilco_ec_remove,
};

module_platform_driver(wilco_ec_driver);

MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>");
MODULE_AUTHOR("Duncan Laurie <dlaurie@chromium.org>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ChromeOS Wilco Embedded Controller driver");
MODULE_ALIAS("platform:" DRV_NAME);
Loading