Re: [PATCH v2 2/2] cros_ec: Move cros_ec_dev module to drivers/mfd
From: Gwendal Grignou
Date: Fri Dec 01 2017 - 14:23:57 EST
Reviewed-by: Gwendal Grignou <gwendal@xxxxxxxxxxxx>
On Thu, Nov 30, 2017 at 12:50 PM, Guenter Roeck <groeck@xxxxxxxxxx> wrote:
> On Mon, Nov 20, 2017 at 8:15 AM, Thierry Escande
> <thierry.escande@xxxxxxxxxxxxx> wrote:
>> The cros_ec_dev module is responsible for registering the MFD devices
>> attached to the ChromeOS EC. This patch moves this module to drivers/mfd
>> so calls to mfd_add_devices() are not done from outside the MFD subtree
>> anymore.
>>
>> Signed-off-by: Thierry Escande <thierry.escande@xxxxxxxxxxxxx>
>
> Tested-by: Guenter Roeck <groeck@xxxxxxxxxxxx>
>
>> ---
>> drivers/mfd/Kconfig | 10 +
>> drivers/mfd/Makefile | 1 +
>> drivers/mfd/cros_ec_dev.c | 552 ++++++++++++++++++++++++++++
>> drivers/mfd/cros_ec_dev.h | 52 +++
>> drivers/platform/chrome/Kconfig | 10 -
>> drivers/platform/chrome/Makefile | 1 -
>> drivers/platform/chrome/cros_ec_debugfs.c | 3 -
>> drivers/platform/chrome/cros_ec_debugfs.h | 27 --
>> drivers/platform/chrome/cros_ec_dev.c | 553 -----------------------------
>> drivers/platform/chrome/cros_ec_dev.h | 52 ---
>> drivers/platform/chrome/cros_ec_lightbar.c | 2 -
>> drivers/platform/chrome/cros_ec_sysfs.c | 2 -
>> include/linux/mfd/cros_ec.h | 4 +
>> 13 files changed, 619 insertions(+), 650 deletions(-)
>> create mode 100644 drivers/mfd/cros_ec_dev.c
>> create mode 100644 drivers/mfd/cros_ec_dev.h
>> delete mode 100644 drivers/platform/chrome/cros_ec_debugfs.h
>> delete mode 100644 drivers/platform/chrome/cros_ec_dev.c
>> delete mode 100644 drivers/platform/chrome/cros_ec_dev.h
>>
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>> index 1d20a80..538a2ae 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -222,6 +222,16 @@ config MFD_CROS_EC_SPI
>> response time cannot be guaranteed, we support ignoring
>> 'pre-amble' bytes before the response actually starts.
>>
>> +config MFD_CROS_EC_CHARDEV
>> + tristate "Chrome OS Embedded Controller userspace device interface"
>> + depends on MFD_CROS_EC
>> + select CROS_EC_CTL
>> + ---help---
>> + This driver adds support to talk with the ChromeOS EC from userspace.
>> +
>> + If you have a supported Chromebook, choose Y or M here.
>> + The module will be called cros_ec_dev.
>> +
>> config MFD_ASIC3
>> bool "Compaq ASIC3"
>> depends on GPIOLIB && ARM
>> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
>> index d9474ad..fcd8af8 100644
>> --- a/drivers/mfd/Makefile
>> +++ b/drivers/mfd/Makefile
>> @@ -17,6 +17,7 @@ cros_ec_core-$(CONFIG_ACPI) += cros_ec_acpi_gpe.o
>> obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
>> obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
>> obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
>> +obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
>> obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
>>
>> rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
>> diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
>> new file mode 100644
>> index 0000000..e4fafdd
>> --- /dev/null
>> +++ b/drivers/mfd/cros_ec_dev.c
>> @@ -0,0 +1,552 @@
>> +/*
>> + * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
>> + *
>> + * Copyright (C) 2014 Google, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/fs.h>
>> +#include <linux/mfd/core.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm.h>
>> +#include <linux/slab.h>
>> +#include <linux/uaccess.h>
>> +
>> +#include "cros_ec_dev.h"
>> +
>> +#define DRV_NAME "cros-ec-dev"
>> +
>> +/* Device variables */
>> +#define CROS_MAX_DEV 128
>> +static int ec_major;
>> +
>> +static const struct attribute_group *cros_ec_groups[] = {
>> + &cros_ec_attr_group,
>> + &cros_ec_lightbar_attr_group,
>> + &cros_ec_vbc_attr_group,
>> + NULL,
>> +};
>> +
>> +static struct class cros_class = {
>> + .owner = THIS_MODULE,
>> + .name = "chromeos",
>> + .dev_groups = cros_ec_groups,
>> +};
>> +
>> +/* Basic communication */
>> +static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
>> +{
>> + struct ec_response_get_version *resp;
>> + static const char * const current_image_name[] = {
>> + "unknown", "read-only", "read-write", "invalid",
>> + };
>> + struct cros_ec_command *msg;
>> + int ret;
>> +
>> + msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
>> + if (!msg)
>> + return -ENOMEM;
>> +
>> + msg->version = 0;
>> + msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
>> + msg->insize = sizeof(*resp);
>> + msg->outsize = 0;
>> +
>> + ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> + if (ret < 0)
>> + goto exit;
>> +
>> + if (msg->result != EC_RES_SUCCESS) {
>> + snprintf(str, maxlen,
>> + "%s\nUnknown EC version: EC returned %d\n",
>> + CROS_EC_DEV_VERSION, msg->result);
>> + ret = -EINVAL;
>> + goto exit;
>> + }
>> +
>> + resp = (struct ec_response_get_version *)msg->data;
>> + if (resp->current_image >= ARRAY_SIZE(current_image_name))
>> + resp->current_image = 3; /* invalid */
>> +
>> + snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION,
>> + resp->version_string_ro, resp->version_string_rw,
>> + current_image_name[resp->current_image]);
>> +
>> + ret = 0;
>> +exit:
>> + kfree(msg);
>> + return ret;
>> +}
>> +
>> +static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
>> +{
>> + struct cros_ec_command *msg;
>> + int ret;
>> +
>> + if (ec->features[0] == -1U && ec->features[1] == -1U) {
>> + /* features bitmap not read yet */
>> +
>> + msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
>> + if (!msg)
>> + return -ENOMEM;
>> +
>> + msg->version = 0;
>> + msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
>> + msg->insize = sizeof(ec->features);
>> + msg->outsize = 0;
>> +
>> + ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> + if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> + dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
>> + ret, msg->result);
>> + memset(ec->features, 0, sizeof(ec->features));
>> + }
>> +
>> + memcpy(ec->features, msg->data, sizeof(ec->features));
>> +
>> + dev_dbg(ec->dev, "EC features %08x %08x\n",
>> + ec->features[0], ec->features[1]);
>> +
>> + kfree(msg);
>> + }
>> +
>> + return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
>> +}
>> +
>> +/* Device file ops */
>> +static int ec_device_open(struct inode *inode, struct file *filp)
>> +{
>> + struct cros_ec_dev *ec = container_of(inode->i_cdev,
>> + struct cros_ec_dev, cdev);
>> + filp->private_data = ec;
>> + nonseekable_open(inode, filp);
>> + return 0;
>> +}
>> +
>> +static int ec_device_release(struct inode *inode, struct file *filp)
>> +{
>> + return 0;
>> +}
>> +
>> +static ssize_t ec_device_read(struct file *filp, char __user *buffer,
>> + size_t length, loff_t *offset)
>> +{
>> + struct cros_ec_dev *ec = filp->private_data;
>> + char msg[sizeof(struct ec_response_get_version) +
>> + sizeof(CROS_EC_DEV_VERSION)];
>> + size_t count;
>> + int ret;
>> +
>> + if (*offset != 0)
>> + return 0;
>> +
>> + ret = ec_get_version(ec, msg, sizeof(msg));
>> + if (ret)
>> + return ret;
>> +
>> + count = min(length, strlen(msg));
>> +
>> + if (copy_to_user(buffer, msg, count))
>> + return -EFAULT;
>> +
>> + *offset = count;
>> + return count;
>> +}
>> +
>> +/* Ioctls */
>> +static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
>> +{
>> + long ret;
>> + struct cros_ec_command u_cmd;
>> + struct cros_ec_command *s_cmd;
>> +
>> + if (copy_from_user(&u_cmd, arg, sizeof(u_cmd)))
>> + return -EFAULT;
>> +
>> + if ((u_cmd.outsize > EC_MAX_MSG_BYTES) ||
>> + (u_cmd.insize > EC_MAX_MSG_BYTES))
>> + return -EINVAL;
>> +
>> + s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
>> + GFP_KERNEL);
>> + if (!s_cmd)
>> + return -ENOMEM;
>> +
>> + if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) {
>> + ret = -EFAULT;
>> + goto exit;
>> + }
>> +
>> + if (u_cmd.outsize != s_cmd->outsize ||
>> + u_cmd.insize != s_cmd->insize) {
>> + ret = -EINVAL;
>> + goto exit;
>> + }
>> +
>> + s_cmd->command += ec->cmd_offset;
>> + ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd);
>> + /* Only copy data to userland if data was received. */
>> + if (ret < 0)
>> + goto exit;
>> +
>> + if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize))
>> + ret = -EFAULT;
>> +exit:
>> + kfree(s_cmd);
>> + return ret;
>> +}
>> +
>> +static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg)
>> +{
>> + struct cros_ec_device *ec_dev = ec->ec_dev;
>> + struct cros_ec_readmem s_mem = { };
>> + long num;
>> +
>> + /* Not every platform supports direct reads */
>> + if (!ec_dev->cmd_readmem)
>> + return -ENOTTY;
>> +
>> + if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
>> + return -EFAULT;
>> +
>> + num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes,
>> + s_mem.buffer);
>> + if (num <= 0)
>> + return num;
>> +
>> + if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
>> + return -EFAULT;
>> +
>> + return 0;
>> +}
>> +
>> +static long ec_device_ioctl(struct file *filp, unsigned int cmd,
>> + unsigned long arg)
>> +{
>> + struct cros_ec_dev *ec = filp->private_data;
>> +
>> + if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
>> + return -ENOTTY;
>> +
>> + switch (cmd) {
>> + case CROS_EC_DEV_IOCXCMD:
>> + return ec_device_ioctl_xcmd(ec, (void __user *)arg);
>> + case CROS_EC_DEV_IOCRDMEM:
>> + return ec_device_ioctl_readmem(ec, (void __user *)arg);
>> + }
>> +
>> + return -ENOTTY;
>> +}
>> +
>> +/* Module initialization */
>> +static const struct file_operations fops = {
>> + .open = ec_device_open,
>> + .release = ec_device_release,
>> + .read = ec_device_read,
>> + .unlocked_ioctl = ec_device_ioctl,
>> +#ifdef CONFIG_COMPAT
>> + .compat_ioctl = ec_device_ioctl,
>> +#endif
>> +};
>> +
>> +static void __remove(struct device *dev)
>> +{
>> + struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
>> + class_dev);
>> + kfree(ec);
>> +}
>> +
>> +static void cros_ec_sensors_register(struct cros_ec_dev *ec)
>> +{
>> + /*
>> + * Issue a command to get the number of sensor reported.
>> + * Build an array of sensors driver and register them all.
>> + */
>> + int ret, i, id, sensor_num;
>> + struct mfd_cell *sensor_cells;
>> + struct cros_ec_sensor_platform *sensor_platforms;
>> + int sensor_type[MOTIONSENSE_TYPE_MAX];
>> + struct ec_params_motion_sense *params;
>> + struct ec_response_motion_sense *resp;
>> + struct cros_ec_command *msg;
>> +
>> + msg = kzalloc(sizeof(struct cros_ec_command) +
>> + max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
>> + if (msg == NULL)
>> + return;
>> +
>> + msg->version = 2;
>> + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>> + msg->outsize = sizeof(*params);
>> + msg->insize = sizeof(*resp);
>> +
>> + params = (struct ec_params_motion_sense *)msg->data;
>> + params->cmd = MOTIONSENSE_CMD_DUMP;
>> +
>> + ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> + if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> + dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
>> + ret, msg->result);
>> + goto error;
>> + }
>> +
>> + resp = (struct ec_response_motion_sense *)msg->data;
>> + sensor_num = resp->dump.sensor_count;
>> + /* Allocate 2 extra sensors in case lid angle or FIFO are needed */
>> + sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
>> + GFP_KERNEL);
>> + if (sensor_cells == NULL)
>> + goto error;
>> +
>> + sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
>> + (sensor_num + 1), GFP_KERNEL);
>> + if (sensor_platforms == NULL)
>> + goto error_platforms;
>> +
>> + memset(sensor_type, 0, sizeof(sensor_type));
>> + id = 0;
>> + for (i = 0; i < sensor_num; i++) {
>> + params->cmd = MOTIONSENSE_CMD_INFO;
>> + params->info.sensor_num = i;
>> + ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> + if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> + dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
>> + i, ret, msg->result);
>> + continue;
>> + }
>> + switch (resp->info.type) {
>> + case MOTIONSENSE_TYPE_ACCEL:
>> + sensor_cells[id].name = "cros-ec-accel";
>> + break;
>> + case MOTIONSENSE_TYPE_BARO:
>> + sensor_cells[id].name = "cros-ec-baro";
>> + break;
>> + case MOTIONSENSE_TYPE_GYRO:
>> + sensor_cells[id].name = "cros-ec-gyro";
>> + break;
>> + case MOTIONSENSE_TYPE_MAG:
>> + sensor_cells[id].name = "cros-ec-mag";
>> + break;
>> + case MOTIONSENSE_TYPE_PROX:
>> + sensor_cells[id].name = "cros-ec-prox";
>> + break;
>> + case MOTIONSENSE_TYPE_LIGHT:
>> + sensor_cells[id].name = "cros-ec-light";
>> + break;
>> + case MOTIONSENSE_TYPE_ACTIVITY:
>> + sensor_cells[id].name = "cros-ec-activity";
>> + break;
>> + default:
>> + dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
>> + continue;
>> + }
>> + sensor_platforms[id].sensor_num = i;
>> + sensor_cells[id].id = sensor_type[resp->info.type];
>> + sensor_cells[id].platform_data = &sensor_platforms[id];
>> + sensor_cells[id].pdata_size =
>> + sizeof(struct cros_ec_sensor_platform);
>> +
>> + sensor_type[resp->info.type]++;
>> + id++;
>> + }
>> + if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
>> + sensor_platforms[id].sensor_num = sensor_num;
>> +
>> + sensor_cells[id].name = "cros-ec-angle";
>> + sensor_cells[id].id = 0;
>> + sensor_cells[id].platform_data = &sensor_platforms[id];
>> + sensor_cells[id].pdata_size =
>> + sizeof(struct cros_ec_sensor_platform);
>> + id++;
>> + }
>> + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
>> + sensor_cells[id].name = "cros-ec-ring";
>> + id++;
>> + }
>> +
>> + ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
>> + NULL, 0, NULL);
>> + if (ret)
>> + dev_err(ec->dev, "failed to add EC sensors\n");
>> +
>> + kfree(sensor_platforms);
>> +error_platforms:
>> + kfree(sensor_cells);
>> +error:
>> + kfree(msg);
>> +}
>> +
>> +static int ec_device_probe(struct platform_device *pdev)
>> +{
>> + int retval = -ENOMEM;
>> + struct device *dev = &pdev->dev;
>> + struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
>> + struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
>> +
>> + if (!ec)
>> + return retval;
>> +
>> + dev_set_drvdata(dev, ec);
>> + ec->ec_dev = dev_get_drvdata(dev->parent);
>> + ec->dev = dev;
>> + ec->cmd_offset = ec_platform->cmd_offset;
>> + ec->features[0] = -1U; /* Not cached yet */
>> + ec->features[1] = -1U; /* Not cached yet */
>> + device_initialize(&ec->class_dev);
>> + cdev_init(&ec->cdev, &fops);
>> +
>> + /*
>> + * Add the class device
>> + * Link to the character device for creating the /dev entry
>> + * in devtmpfs.
>> + */
>> + ec->class_dev.devt = MKDEV(ec_major, pdev->id);
>> + ec->class_dev.class = &cros_class;
>> + ec->class_dev.parent = dev;
>> + ec->class_dev.release = __remove;
>> +
>> + retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
>> + if (retval) {
>> + dev_err(dev, "dev_set_name failed => %d\n", retval);
>> + goto failed;
>> + }
>> +
>> + retval = cdev_device_add(&ec->cdev, &ec->class_dev);
>> + if (retval) {
>> + dev_err(dev, "cdev_device_add failed => %d\n", retval);
>> + goto failed;
>> + }
>> +
>> + if (cros_ec_debugfs_init(ec))
>> + dev_warn(dev, "failed to create debugfs directory\n");
>> +
>> + /* check whether this EC is a sensor hub. */
>> + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
>> + cros_ec_sensors_register(ec);
>> +
>> + /* Take control of the lightbar from the EC. */
>> + lb_manual_suspend_ctrl(ec, 1);
>> +
>> + return 0;
>> +
>> +failed:
>> + put_device(&ec->class_dev);
>> + return retval;
>> +}
>> +
>> +static int ec_device_remove(struct platform_device *pdev)
>> +{
>> + struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
>> +
>> + /* Let the EC take over the lightbar again. */
>> + lb_manual_suspend_ctrl(ec, 0);
>> +
>> + cros_ec_debugfs_remove(ec);
>> +
>> + cdev_del(&ec->cdev);
>> + device_unregister(&ec->class_dev);
>> + return 0;
>> +}
>> +
>> +static const struct platform_device_id cros_ec_id[] = {
>> + { DRV_NAME, 0 },
>> + { /* sentinel */ },
>> +};
>> +MODULE_DEVICE_TABLE(platform, cros_ec_id);
>> +
>> +static __maybe_unused int ec_device_suspend(struct device *dev)
>> +{
>> + struct cros_ec_dev *ec = dev_get_drvdata(dev);
>> +
>> + lb_suspend(ec);
>> +
>> + return 0;
>> +}
>> +
>> +static __maybe_unused int ec_device_resume(struct device *dev)
>> +{
>> + struct cros_ec_dev *ec = dev_get_drvdata(dev);
>> +
>> + lb_resume(ec);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct dev_pm_ops cros_ec_dev_pm_ops = {
>> +#ifdef CONFIG_PM_SLEEP
>> + .suspend = ec_device_suspend,
>> + .resume = ec_device_resume,
>> +#endif
>> +};
>> +
>> +static struct platform_driver cros_ec_dev_driver = {
>> + .driver = {
>> + .name = DRV_NAME,
>> + .pm = &cros_ec_dev_pm_ops,
>> + },
>> + .probe = ec_device_probe,
>> + .remove = ec_device_remove,
>> +};
>> +
>> +static int __init cros_ec_dev_init(void)
>> +{
>> + int ret;
>> + dev_t dev = 0;
>> +
>> + ret = class_register(&cros_class);
>> + if (ret) {
>> + pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
>> + return ret;
>> + }
>> +
>> + /* Get a range of minor numbers (starting with 0) to work with */
>> + ret = alloc_chrdev_region(&dev, 0, CROS_MAX_DEV, CROS_EC_DEV_NAME);
>> + if (ret < 0) {
>> + pr_err(CROS_EC_DEV_NAME ": alloc_chrdev_region() failed\n");
>> + goto failed_chrdevreg;
>> + }
>> + ec_major = MAJOR(dev);
>> +
>> + /* Register the driver */
>> + ret = platform_driver_register(&cros_ec_dev_driver);
>> + if (ret < 0) {
>> + pr_warn(CROS_EC_DEV_NAME ": can't register driver: %d\n", ret);
>> + goto failed_devreg;
>> + }
>> + return 0;
>> +
>> +failed_devreg:
>> + unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
>> +failed_chrdevreg:
>> + class_unregister(&cros_class);
>> + return ret;
>> +}
>> +
>> +static void __exit cros_ec_dev_exit(void)
>> +{
>> + platform_driver_unregister(&cros_ec_dev_driver);
>> + unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
>> + class_unregister(&cros_class);
>> +}
>> +
>> +module_init(cros_ec_dev_init);
>> +module_exit(cros_ec_dev_exit);
>> +
>> +MODULE_ALIAS("platform:" DRV_NAME);
>> +MODULE_AUTHOR("Bill Richardson <wfrichar@xxxxxxxxxxxx>");
>> +MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
>> +MODULE_VERSION("1.0");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/mfd/cros_ec_dev.h b/drivers/mfd/cros_ec_dev.h
>> new file mode 100644
>> index 0000000..45e9453
>> --- /dev/null
>> +++ b/drivers/mfd/cros_ec_dev.h
>> @@ -0,0 +1,52 @@
>> +/*
>> + * cros_ec_dev - expose the Chrome OS Embedded Controller to userspace
>> + *
>> + * Copyright (C) 2014 Google, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef _CROS_EC_DEV_H_
>> +#define _CROS_EC_DEV_H_
>> +
>> +#include <linux/ioctl.h>
>> +#include <linux/types.h>
>> +#include <linux/mfd/cros_ec.h>
>> +
>> +#define CROS_EC_DEV_VERSION "1.0.0"
>> +
>> +/*
>> + * @offset: within EC_LPC_ADDR_MEMMAP region
>> + * @bytes: number of bytes to read. zero means "read a string" (including '\0')
>> + * (at most only EC_MEMMAP_SIZE bytes can be read)
>> + * @buffer: where to store the result
>> + * ioctl returns the number of bytes read, negative on error
>> + */
>> +struct cros_ec_readmem {
>> + uint32_t offset;
>> + uint32_t bytes;
>> + uint8_t buffer[EC_MEMMAP_SIZE];
>> +};
>> +
>> +#define CROS_EC_DEV_IOC 0xEC
>> +#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
>> +#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
>> +
>> +/* Lightbar utilities */
>> +extern bool ec_has_lightbar(struct cros_ec_dev *ec);
>> +extern int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable);
>> +extern int lb_suspend(struct cros_ec_dev *ec);
>> +extern int lb_resume(struct cros_ec_dev *ec);
>> +
>> +#endif /* _CROS_EC_DEV_H_ */
>> diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
>> index bffc892..e728a96 100644
>> --- a/drivers/platform/chrome/Kconfig
>> +++ b/drivers/platform/chrome/Kconfig
>> @@ -38,16 +38,6 @@ config CHROMEOS_PSTORE
>> If you have a supported Chromebook, choose Y or M here.
>> The module will be called chromeos_pstore.
>>
>> -config CROS_EC_CHARDEV
>> - tristate "Chrome OS Embedded Controller userspace device interface"
>> - depends on MFD_CROS_EC
>> - select CROS_EC_CTL
>> - ---help---
>> - This driver adds support to talk with the ChromeOS EC from userspace.
>> -
>> - If you have a supported Chromebook, choose Y or M here.
>> - The module will be called cros_ec_dev.
>> -
>> config CROS_EC_CTL
>> tristate
>>
>> diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
>> index bc239ec..ff3b369 100644
>> --- a/drivers/platform/chrome/Makefile
>> +++ b/drivers/platform/chrome/Makefile
>> @@ -5,7 +5,6 @@ obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
>> cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \
>> cros_ec_vbc.o cros_ec_debugfs.o
>> obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o
>> -obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_dev.o
>> cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_reg.o
>> cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
>> obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
>> diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
>> index d0b8ce0..98a35d3 100644
>> --- a/drivers/platform/chrome/cros_ec_debugfs.c
>> +++ b/drivers/platform/chrome/cros_ec_debugfs.c
>> @@ -29,9 +29,6 @@
>> #include <linux/slab.h>
>> #include <linux/wait.h>
>>
>> -#include "cros_ec_dev.h"
>> -#include "cros_ec_debugfs.h"
>> -
>> #define LOG_SHIFT 14
>> #define LOG_SIZE (1 << LOG_SHIFT)
>> #define LOG_POLL_SEC 10
>> diff --git a/drivers/platform/chrome/cros_ec_debugfs.h b/drivers/platform/chrome/cros_ec_debugfs.h
>> deleted file mode 100644
>> index 1ff3a50..0000000
>> --- a/drivers/platform/chrome/cros_ec_debugfs.h
>> +++ /dev/null
>> @@ -1,27 +0,0 @@
>> -/*
>> - * Copyright 2015 Google, Inc.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or
>> - * (at your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> - * GNU General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> - */
>> -
>> -#ifndef _DRV_CROS_EC_DEBUGFS_H_
>> -#define _DRV_CROS_EC_DEBUGFS_H_
>> -
>> -#include "cros_ec_dev.h"
>> -
>> -/* debugfs stuff */
>> -int cros_ec_debugfs_init(struct cros_ec_dev *ec);
>> -void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
>> -
>> -#endif /* _DRV_CROS_EC_DEBUGFS_H_ */
>> diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
>> deleted file mode 100644
>> index daf0ffd..0000000
>> --- a/drivers/platform/chrome/cros_ec_dev.c
>> +++ /dev/null
>> @@ -1,553 +0,0 @@
>> -/*
>> - * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
>> - *
>> - * Copyright (C) 2014 Google, Inc.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or
>> - * (at your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> - * GNU General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> - */
>> -
>> -#include <linux/fs.h>
>> -#include <linux/mfd/core.h>
>> -#include <linux/module.h>
>> -#include <linux/platform_device.h>
>> -#include <linux/pm.h>
>> -#include <linux/slab.h>
>> -#include <linux/uaccess.h>
>> -
>> -#include "cros_ec_debugfs.h"
>> -#include "cros_ec_dev.h"
>> -
>> -#define DRV_NAME "cros-ec-dev"
>> -
>> -/* Device variables */
>> -#define CROS_MAX_DEV 128
>> -static int ec_major;
>> -
>> -static const struct attribute_group *cros_ec_groups[] = {
>> - &cros_ec_attr_group,
>> - &cros_ec_lightbar_attr_group,
>> - &cros_ec_vbc_attr_group,
>> - NULL,
>> -};
>> -
>> -static struct class cros_class = {
>> - .owner = THIS_MODULE,
>> - .name = "chromeos",
>> - .dev_groups = cros_ec_groups,
>> -};
>> -
>> -/* Basic communication */
>> -static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
>> -{
>> - struct ec_response_get_version *resp;
>> - static const char * const current_image_name[] = {
>> - "unknown", "read-only", "read-write", "invalid",
>> - };
>> - struct cros_ec_command *msg;
>> - int ret;
>> -
>> - msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
>> - if (!msg)
>> - return -ENOMEM;
>> -
>> - msg->version = 0;
>> - msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
>> - msg->insize = sizeof(*resp);
>> - msg->outsize = 0;
>> -
>> - ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> - if (ret < 0)
>> - goto exit;
>> -
>> - if (msg->result != EC_RES_SUCCESS) {
>> - snprintf(str, maxlen,
>> - "%s\nUnknown EC version: EC returned %d\n",
>> - CROS_EC_DEV_VERSION, msg->result);
>> - ret = -EINVAL;
>> - goto exit;
>> - }
>> -
>> - resp = (struct ec_response_get_version *)msg->data;
>> - if (resp->current_image >= ARRAY_SIZE(current_image_name))
>> - resp->current_image = 3; /* invalid */
>> -
>> - snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION,
>> - resp->version_string_ro, resp->version_string_rw,
>> - current_image_name[resp->current_image]);
>> -
>> - ret = 0;
>> -exit:
>> - kfree(msg);
>> - return ret;
>> -}
>> -
>> -static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
>> -{
>> - struct cros_ec_command *msg;
>> - int ret;
>> -
>> - if (ec->features[0] == -1U && ec->features[1] == -1U) {
>> - /* features bitmap not read yet */
>> -
>> - msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
>> - if (!msg)
>> - return -ENOMEM;
>> -
>> - msg->version = 0;
>> - msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
>> - msg->insize = sizeof(ec->features);
>> - msg->outsize = 0;
>> -
>> - ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> - if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> - dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
>> - ret, msg->result);
>> - memset(ec->features, 0, sizeof(ec->features));
>> - }
>> -
>> - memcpy(ec->features, msg->data, sizeof(ec->features));
>> -
>> - dev_dbg(ec->dev, "EC features %08x %08x\n",
>> - ec->features[0], ec->features[1]);
>> -
>> - kfree(msg);
>> - }
>> -
>> - return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
>> -}
>> -
>> -/* Device file ops */
>> -static int ec_device_open(struct inode *inode, struct file *filp)
>> -{
>> - struct cros_ec_dev *ec = container_of(inode->i_cdev,
>> - struct cros_ec_dev, cdev);
>> - filp->private_data = ec;
>> - nonseekable_open(inode, filp);
>> - return 0;
>> -}
>> -
>> -static int ec_device_release(struct inode *inode, struct file *filp)
>> -{
>> - return 0;
>> -}
>> -
>> -static ssize_t ec_device_read(struct file *filp, char __user *buffer,
>> - size_t length, loff_t *offset)
>> -{
>> - struct cros_ec_dev *ec = filp->private_data;
>> - char msg[sizeof(struct ec_response_get_version) +
>> - sizeof(CROS_EC_DEV_VERSION)];
>> - size_t count;
>> - int ret;
>> -
>> - if (*offset != 0)
>> - return 0;
>> -
>> - ret = ec_get_version(ec, msg, sizeof(msg));
>> - if (ret)
>> - return ret;
>> -
>> - count = min(length, strlen(msg));
>> -
>> - if (copy_to_user(buffer, msg, count))
>> - return -EFAULT;
>> -
>> - *offset = count;
>> - return count;
>> -}
>> -
>> -/* Ioctls */
>> -static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
>> -{
>> - long ret;
>> - struct cros_ec_command u_cmd;
>> - struct cros_ec_command *s_cmd;
>> -
>> - if (copy_from_user(&u_cmd, arg, sizeof(u_cmd)))
>> - return -EFAULT;
>> -
>> - if ((u_cmd.outsize > EC_MAX_MSG_BYTES) ||
>> - (u_cmd.insize > EC_MAX_MSG_BYTES))
>> - return -EINVAL;
>> -
>> - s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
>> - GFP_KERNEL);
>> - if (!s_cmd)
>> - return -ENOMEM;
>> -
>> - if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) {
>> - ret = -EFAULT;
>> - goto exit;
>> - }
>> -
>> - if (u_cmd.outsize != s_cmd->outsize ||
>> - u_cmd.insize != s_cmd->insize) {
>> - ret = -EINVAL;
>> - goto exit;
>> - }
>> -
>> - s_cmd->command += ec->cmd_offset;
>> - ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd);
>> - /* Only copy data to userland if data was received. */
>> - if (ret < 0)
>> - goto exit;
>> -
>> - if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize))
>> - ret = -EFAULT;
>> -exit:
>> - kfree(s_cmd);
>> - return ret;
>> -}
>> -
>> -static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg)
>> -{
>> - struct cros_ec_device *ec_dev = ec->ec_dev;
>> - struct cros_ec_readmem s_mem = { };
>> - long num;
>> -
>> - /* Not every platform supports direct reads */
>> - if (!ec_dev->cmd_readmem)
>> - return -ENOTTY;
>> -
>> - if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
>> - return -EFAULT;
>> -
>> - num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes,
>> - s_mem.buffer);
>> - if (num <= 0)
>> - return num;
>> -
>> - if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
>> - return -EFAULT;
>> -
>> - return 0;
>> -}
>> -
>> -static long ec_device_ioctl(struct file *filp, unsigned int cmd,
>> - unsigned long arg)
>> -{
>> - struct cros_ec_dev *ec = filp->private_data;
>> -
>> - if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
>> - return -ENOTTY;
>> -
>> - switch (cmd) {
>> - case CROS_EC_DEV_IOCXCMD:
>> - return ec_device_ioctl_xcmd(ec, (void __user *)arg);
>> - case CROS_EC_DEV_IOCRDMEM:
>> - return ec_device_ioctl_readmem(ec, (void __user *)arg);
>> - }
>> -
>> - return -ENOTTY;
>> -}
>> -
>> -/* Module initialization */
>> -static const struct file_operations fops = {
>> - .open = ec_device_open,
>> - .release = ec_device_release,
>> - .read = ec_device_read,
>> - .unlocked_ioctl = ec_device_ioctl,
>> -#ifdef CONFIG_COMPAT
>> - .compat_ioctl = ec_device_ioctl,
>> -#endif
>> -};
>> -
>> -static void __remove(struct device *dev)
>> -{
>> - struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
>> - class_dev);
>> - kfree(ec);
>> -}
>> -
>> -static void cros_ec_sensors_register(struct cros_ec_dev *ec)
>> -{
>> - /*
>> - * Issue a command to get the number of sensor reported.
>> - * Build an array of sensors driver and register them all.
>> - */
>> - int ret, i, id, sensor_num;
>> - struct mfd_cell *sensor_cells;
>> - struct cros_ec_sensor_platform *sensor_platforms;
>> - int sensor_type[MOTIONSENSE_TYPE_MAX];
>> - struct ec_params_motion_sense *params;
>> - struct ec_response_motion_sense *resp;
>> - struct cros_ec_command *msg;
>> -
>> - msg = kzalloc(sizeof(struct cros_ec_command) +
>> - max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
>> - if (msg == NULL)
>> - return;
>> -
>> - msg->version = 2;
>> - msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>> - msg->outsize = sizeof(*params);
>> - msg->insize = sizeof(*resp);
>> -
>> - params = (struct ec_params_motion_sense *)msg->data;
>> - params->cmd = MOTIONSENSE_CMD_DUMP;
>> -
>> - ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> - if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> - dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
>> - ret, msg->result);
>> - goto error;
>> - }
>> -
>> - resp = (struct ec_response_motion_sense *)msg->data;
>> - sensor_num = resp->dump.sensor_count;
>> - /* Allocate 2 extra sensors in case lid angle or FIFO are needed */
>> - sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
>> - GFP_KERNEL);
>> - if (sensor_cells == NULL)
>> - goto error;
>> -
>> - sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
>> - (sensor_num + 1), GFP_KERNEL);
>> - if (sensor_platforms == NULL)
>> - goto error_platforms;
>> -
>> - memset(sensor_type, 0, sizeof(sensor_type));
>> - id = 0;
>> - for (i = 0; i < sensor_num; i++) {
>> - params->cmd = MOTIONSENSE_CMD_INFO;
>> - params->info.sensor_num = i;
>> - ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> - if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> - dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
>> - i, ret, msg->result);
>> - continue;
>> - }
>> - switch (resp->info.type) {
>> - case MOTIONSENSE_TYPE_ACCEL:
>> - sensor_cells[id].name = "cros-ec-accel";
>> - break;
>> - case MOTIONSENSE_TYPE_BARO:
>> - sensor_cells[id].name = "cros-ec-baro";
>> - break;
>> - case MOTIONSENSE_TYPE_GYRO:
>> - sensor_cells[id].name = "cros-ec-gyro";
>> - break;
>> - case MOTIONSENSE_TYPE_MAG:
>> - sensor_cells[id].name = "cros-ec-mag";
>> - break;
>> - case MOTIONSENSE_TYPE_PROX:
>> - sensor_cells[id].name = "cros-ec-prox";
>> - break;
>> - case MOTIONSENSE_TYPE_LIGHT:
>> - sensor_cells[id].name = "cros-ec-light";
>> - break;
>> - case MOTIONSENSE_TYPE_ACTIVITY:
>> - sensor_cells[id].name = "cros-ec-activity";
>> - break;
>> - default:
>> - dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
>> - continue;
>> - }
>> - sensor_platforms[id].sensor_num = i;
>> - sensor_cells[id].id = sensor_type[resp->info.type];
>> - sensor_cells[id].platform_data = &sensor_platforms[id];
>> - sensor_cells[id].pdata_size =
>> - sizeof(struct cros_ec_sensor_platform);
>> -
>> - sensor_type[resp->info.type]++;
>> - id++;
>> - }
>> - if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
>> - sensor_platforms[id].sensor_num = sensor_num;
>> -
>> - sensor_cells[id].name = "cros-ec-angle";
>> - sensor_cells[id].id = 0;
>> - sensor_cells[id].platform_data = &sensor_platforms[id];
>> - sensor_cells[id].pdata_size =
>> - sizeof(struct cros_ec_sensor_platform);
>> - id++;
>> - }
>> - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
>> - sensor_cells[id].name = "cros-ec-ring";
>> - id++;
>> - }
>> -
>> - ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
>> - NULL, 0, NULL);
>> - if (ret)
>> - dev_err(ec->dev, "failed to add EC sensors\n");
>> -
>> - kfree(sensor_platforms);
>> -error_platforms:
>> - kfree(sensor_cells);
>> -error:
>> - kfree(msg);
>> -}
>> -
>> -static int ec_device_probe(struct platform_device *pdev)
>> -{
>> - int retval = -ENOMEM;
>> - struct device *dev = &pdev->dev;
>> - struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
>> - struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
>> -
>> - if (!ec)
>> - return retval;
>> -
>> - dev_set_drvdata(dev, ec);
>> - ec->ec_dev = dev_get_drvdata(dev->parent);
>> - ec->dev = dev;
>> - ec->cmd_offset = ec_platform->cmd_offset;
>> - ec->features[0] = -1U; /* Not cached yet */
>> - ec->features[1] = -1U; /* Not cached yet */
>> - device_initialize(&ec->class_dev);
>> - cdev_init(&ec->cdev, &fops);
>> -
>> - /*
>> - * Add the class device
>> - * Link to the character device for creating the /dev entry
>> - * in devtmpfs.
>> - */
>> - ec->class_dev.devt = MKDEV(ec_major, pdev->id);
>> - ec->class_dev.class = &cros_class;
>> - ec->class_dev.parent = dev;
>> - ec->class_dev.release = __remove;
>> -
>> - retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
>> - if (retval) {
>> - dev_err(dev, "dev_set_name failed => %d\n", retval);
>> - goto failed;
>> - }
>> -
>> - retval = cdev_device_add(&ec->cdev, &ec->class_dev);
>> - if (retval) {
>> - dev_err(dev, "cdev_device_add failed => %d\n", retval);
>> - goto failed;
>> - }
>> -
>> - if (cros_ec_debugfs_init(ec))
>> - dev_warn(dev, "failed to create debugfs directory\n");
>> -
>> - /* check whether this EC is a sensor hub. */
>> - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
>> - cros_ec_sensors_register(ec);
>> -
>> - /* Take control of the lightbar from the EC. */
>> - lb_manual_suspend_ctrl(ec, 1);
>> -
>> - return 0;
>> -
>> -failed:
>> - put_device(&ec->class_dev);
>> - return retval;
>> -}
>> -
>> -static int ec_device_remove(struct platform_device *pdev)
>> -{
>> - struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
>> -
>> - /* Let the EC take over the lightbar again. */
>> - lb_manual_suspend_ctrl(ec, 0);
>> -
>> - cros_ec_debugfs_remove(ec);
>> -
>> - cdev_del(&ec->cdev);
>> - device_unregister(&ec->class_dev);
>> - return 0;
>> -}
>> -
>> -static const struct platform_device_id cros_ec_id[] = {
>> - { DRV_NAME, 0 },
>> - { /* sentinel */ },
>> -};
>> -MODULE_DEVICE_TABLE(platform, cros_ec_id);
>> -
>> -static __maybe_unused int ec_device_suspend(struct device *dev)
>> -{
>> - struct cros_ec_dev *ec = dev_get_drvdata(dev);
>> -
>> - lb_suspend(ec);
>> -
>> - return 0;
>> -}
>> -
>> -static __maybe_unused int ec_device_resume(struct device *dev)
>> -{
>> - struct cros_ec_dev *ec = dev_get_drvdata(dev);
>> -
>> - lb_resume(ec);
>> -
>> - return 0;
>> -}
>> -
>> -static const struct dev_pm_ops cros_ec_dev_pm_ops = {
>> -#ifdef CONFIG_PM_SLEEP
>> - .suspend = ec_device_suspend,
>> - .resume = ec_device_resume,
>> -#endif
>> -};
>> -
>> -static struct platform_driver cros_ec_dev_driver = {
>> - .driver = {
>> - .name = DRV_NAME,
>> - .pm = &cros_ec_dev_pm_ops,
>> - },
>> - .probe = ec_device_probe,
>> - .remove = ec_device_remove,
>> -};
>> -
>> -static int __init cros_ec_dev_init(void)
>> -{
>> - int ret;
>> - dev_t dev = 0;
>> -
>> - ret = class_register(&cros_class);
>> - if (ret) {
>> - pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
>> - return ret;
>> - }
>> -
>> - /* Get a range of minor numbers (starting with 0) to work with */
>> - ret = alloc_chrdev_region(&dev, 0, CROS_MAX_DEV, CROS_EC_DEV_NAME);
>> - if (ret < 0) {
>> - pr_err(CROS_EC_DEV_NAME ": alloc_chrdev_region() failed\n");
>> - goto failed_chrdevreg;
>> - }
>> - ec_major = MAJOR(dev);
>> -
>> - /* Register the driver */
>> - ret = platform_driver_register(&cros_ec_dev_driver);
>> - if (ret < 0) {
>> - pr_warn(CROS_EC_DEV_NAME ": can't register driver: %d\n", ret);
>> - goto failed_devreg;
>> - }
>> - return 0;
>> -
>> -failed_devreg:
>> - unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
>> -failed_chrdevreg:
>> - class_unregister(&cros_class);
>> - return ret;
>> -}
>> -
>> -static void __exit cros_ec_dev_exit(void)
>> -{
>> - platform_driver_unregister(&cros_ec_dev_driver);
>> - unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
>> - class_unregister(&cros_class);
>> -}
>> -
>> -module_init(cros_ec_dev_init);
>> -module_exit(cros_ec_dev_exit);
>> -
>> -MODULE_ALIAS("platform:" DRV_NAME);
>> -MODULE_AUTHOR("Bill Richardson <wfrichar@xxxxxxxxxxxx>");
>> -MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
>> -MODULE_VERSION("1.0");
>> -MODULE_LICENSE("GPL");
>> diff --git a/drivers/platform/chrome/cros_ec_dev.h b/drivers/platform/chrome/cros_ec_dev.h
>> deleted file mode 100644
>> index 45e9453..0000000
>> --- a/drivers/platform/chrome/cros_ec_dev.h
>> +++ /dev/null
>> @@ -1,52 +0,0 @@
>> -/*
>> - * cros_ec_dev - expose the Chrome OS Embedded Controller to userspace
>> - *
>> - * Copyright (C) 2014 Google, Inc.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or
>> - * (at your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> - * GNU General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> - */
>> -
>> -#ifndef _CROS_EC_DEV_H_
>> -#define _CROS_EC_DEV_H_
>> -
>> -#include <linux/ioctl.h>
>> -#include <linux/types.h>
>> -#include <linux/mfd/cros_ec.h>
>> -
>> -#define CROS_EC_DEV_VERSION "1.0.0"
>> -
>> -/*
>> - * @offset: within EC_LPC_ADDR_MEMMAP region
>> - * @bytes: number of bytes to read. zero means "read a string" (including '\0')
>> - * (at most only EC_MEMMAP_SIZE bytes can be read)
>> - * @buffer: where to store the result
>> - * ioctl returns the number of bytes read, negative on error
>> - */
>> -struct cros_ec_readmem {
>> - uint32_t offset;
>> - uint32_t bytes;
>> - uint8_t buffer[EC_MEMMAP_SIZE];
>> -};
>> -
>> -#define CROS_EC_DEV_IOC 0xEC
>> -#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
>> -#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
>> -
>> -/* Lightbar utilities */
>> -extern bool ec_has_lightbar(struct cros_ec_dev *ec);
>> -extern int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable);
>> -extern int lb_suspend(struct cros_ec_dev *ec);
>> -extern int lb_resume(struct cros_ec_dev *ec);
>> -
>> -#endif /* _CROS_EC_DEV_H_ */
>> diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
>> index 925d91c..6ea79d4 100644
>> --- a/drivers/platform/chrome/cros_ec_lightbar.c
>> +++ b/drivers/platform/chrome/cros_ec_lightbar.c
>> @@ -33,8 +33,6 @@
>> #include <linux/uaccess.h>
>> #include <linux/slab.h>
>>
>> -#include "cros_ec_dev.h"
>> -
>> /* Rate-limit the lightbar interface to prevent DoS. */
>> static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
>>
>> diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c
>> index 201f11a..d6eebe8 100644
>> --- a/drivers/platform/chrome/cros_ec_sysfs.c
>> +++ b/drivers/platform/chrome/cros_ec_sysfs.c
>> @@ -34,8 +34,6 @@
>> #include <linux/types.h>
>> #include <linux/uaccess.h>
>>
>> -#include "cros_ec_dev.h"
>> -
>> /* Accessor functions */
>>
>> static ssize_t show_ec_reboot(struct device *dev,
>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>> index 4e887ba..c615359 100644
>> --- a/include/linux/mfd/cros_ec.h
>> +++ b/include/linux/mfd/cros_ec.h
>> @@ -322,6 +322,10 @@ extern struct attribute_group cros_ec_attr_group;
>> extern struct attribute_group cros_ec_lightbar_attr_group;
>> extern struct attribute_group cros_ec_vbc_attr_group;
>>
>> +/* debugfs stuff */
>> +int cros_ec_debugfs_init(struct cros_ec_dev *ec);
>> +void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
>> +
>> /* ACPI GPE handler */
>> #ifdef CONFIG_ACPI
>>
>> --
>> 2.7.4
>>