lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 1 Dec 2017 11:23:26 -0800
From:   Gwendal Grignou <gwendal@...omium.org>
To:     Guenter Roeck <groeck@...gle.com>
Cc:     Thierry Escande <thierry.escande@...labora.com>,
        Lee Jones <lee.jones@...aro.org>,
        Benson Leung <bleung@...omium.org>,
        Enric Balletbo i Serra <enric.balletbo@...labora.com>,
        Gwendal Grignou <gwendal@...omium.org>,
        linux-kernel <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v2 2/2] cros_ec: Move cros_ec_dev module to drivers/mfd

Reviewed-by: Gwendal Grignou <gwendal@...omium.org>

On Thu, Nov 30, 2017 at 12:50 PM, Guenter Roeck <groeck@...gle.com> wrote:
> On Mon, Nov 20, 2017 at 8:15 AM, Thierry Escande
> <thierry.escande@...labora.com> 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@...labora.com>
>
> Tested-by: Guenter Roeck <groeck@...omium.org>
>
>> ---
>>  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@...omium.org>");
>> +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@...omium.org>");
>> -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
>>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ