mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-20 00:11:22 +00:00
mfd: cros_ec: Support multiple EC in a system
Chromebooks can have more than one Embedded Controller so the cros_ec device id has to be incremented for each EC registered. Add a new structure to represent multiple EC as different char devices (e.g: /dev/cros_ec, /dev/cros_pd). It connects to cros_ec_device and allows sysfs inferface for cros_pd. Also reduce number of allocated objects, make chromeos sysfs class object a static and add refcounting to prevent object deletion while command is in progress. Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-by: Dmitry Torokhov <dtor@chromium.org> Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Tested-by: Heiko Stuebner <heiko@sntech.de> Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Lee Jones <lee.jones@linaro.org>
This commit is contained in:
parent
d365407079
commit
57b33ff077
@ -275,7 +275,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
|
|||||||
ckdev->dev = dev;
|
ckdev->dev = dev;
|
||||||
dev_set_drvdata(&pdev->dev, ckdev);
|
dev_set_drvdata(&pdev->dev, ckdev);
|
||||||
|
|
||||||
idev->name = ec->ec_name;
|
idev->name = CROS_EC_DEV_NAME;
|
||||||
idev->phys = ec->phys_name;
|
idev->phys = ec->phys_name;
|
||||||
__set_bit(EV_REP, idev->evbit);
|
__set_bit(EV_REP, idev->evbit);
|
||||||
|
|
||||||
|
@ -24,11 +24,29 @@
|
|||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
|
|
||||||
static const struct mfd_cell cros_devs[] = {
|
#define CROS_EC_DEV_EC_INDEX 0
|
||||||
{
|
#define CROS_EC_DEV_PD_INDEX 1
|
||||||
.name = "cros-ec-ctl",
|
|
||||||
.id = PLATFORM_DEVID_AUTO,
|
struct cros_ec_platform ec_p = {
|
||||||
},
|
.ec_name = CROS_EC_DEV_NAME,
|
||||||
|
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cros_ec_platform pd_p = {
|
||||||
|
.ec_name = CROS_EC_DEV_PD_NAME,
|
||||||
|
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mfd_cell ec_cell = {
|
||||||
|
.name = "cros-ec-ctl",
|
||||||
|
.platform_data = &ec_p,
|
||||||
|
.pdata_size = sizeof(ec_p),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mfd_cell ec_pd_cell = {
|
||||||
|
.name = "cros-ec-ctl",
|
||||||
|
.platform_data = &pd_p,
|
||||||
|
.pdata_size = sizeof(pd_p),
|
||||||
};
|
};
|
||||||
|
|
||||||
int cros_ec_register(struct cros_ec_device *ec_dev)
|
int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||||
@ -52,14 +70,34 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||||||
|
|
||||||
cros_ec_query_all(ec_dev);
|
cros_ec_query_all(ec_dev);
|
||||||
|
|
||||||
err = mfd_add_devices(dev, 0, cros_devs,
|
err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell, 1,
|
||||||
ARRAY_SIZE(cros_devs),
|
|
||||||
NULL, ec_dev->irq, NULL);
|
NULL, ec_dev->irq, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(dev, "failed to add mfd devices\n");
|
dev_err(dev,
|
||||||
|
"Failed to register Embedded Controller subdevice %d\n",
|
||||||
|
err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ec_dev->max_passthru) {
|
||||||
|
/*
|
||||||
|
* Register a PD device as well on top of this device.
|
||||||
|
* We make the following assumptions:
|
||||||
|
* - behind an EC, we have a pd
|
||||||
|
* - only one device added.
|
||||||
|
* - the EC is responsive at init time (it is not true for a
|
||||||
|
* sensor hub.
|
||||||
|
*/
|
||||||
|
err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO,
|
||||||
|
&ec_pd_cell, 1, NULL, ec_dev->irq, NULL);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev,
|
||||||
|
"Failed to register Power Delivery subdevice %d\n",
|
||||||
|
err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
|
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
|
||||||
err = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
err = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -302,7 +302,6 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
|
|||||||
ec_dev->irq = client->irq;
|
ec_dev->irq = client->irq;
|
||||||
ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
|
ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
|
||||||
ec_dev->pkt_xfer = cros_ec_pkt_xfer_i2c;
|
ec_dev->pkt_xfer = cros_ec_pkt_xfer_i2c;
|
||||||
ec_dev->ec_name = client->name;
|
|
||||||
ec_dev->phys_name = client->adapter->name;
|
ec_dev->phys_name = client->adapter->name;
|
||||||
ec_dev->din_size = sizeof(struct ec_host_response_i2c) +
|
ec_dev->din_size = sizeof(struct ec_host_response_i2c) +
|
||||||
sizeof(struct ec_response_get_protocol_info);
|
sizeof(struct ec_response_get_protocol_info);
|
||||||
|
@ -637,7 +637,6 @@ static int cros_ec_spi_probe(struct spi_device *spi)
|
|||||||
ec_dev->irq = spi->irq;
|
ec_dev->irq = spi->irq;
|
||||||
ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
|
ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
|
||||||
ec_dev->pkt_xfer = cros_ec_pkt_xfer_spi;
|
ec_dev->pkt_xfer = cros_ec_pkt_xfer_spi;
|
||||||
ec_dev->ec_name = ec_spi->spi->modalias;
|
|
||||||
ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
|
ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
|
||||||
ec_dev->din_size = EC_MSG_PREAMBLE_COUNT +
|
ec_dev->din_size = EC_MSG_PREAMBLE_COUNT +
|
||||||
sizeof(struct ec_host_response) +
|
sizeof(struct ec_host_response) +
|
||||||
|
@ -27,11 +27,22 @@
|
|||||||
|
|
||||||
/* Device variables */
|
/* Device variables */
|
||||||
#define CROS_MAX_DEV 128
|
#define CROS_MAX_DEV 128
|
||||||
static struct class *cros_class;
|
|
||||||
static int ec_major;
|
static int ec_major;
|
||||||
|
|
||||||
|
static const struct attribute_group *cros_ec_groups[] = {
|
||||||
|
&cros_ec_attr_group,
|
||||||
|
&cros_ec_lightbar_attr_group,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct class cros_class = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "chromeos",
|
||||||
|
.dev_groups = cros_ec_groups,
|
||||||
|
};
|
||||||
|
|
||||||
/* Basic communication */
|
/* Basic communication */
|
||||||
static int ec_get_version(struct cros_ec_device *ec, char *str, int maxlen)
|
static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
|
||||||
{
|
{
|
||||||
struct ec_response_get_version *resp;
|
struct ec_response_get_version *resp;
|
||||||
static const char * const current_image_name[] = {
|
static const char * const current_image_name[] = {
|
||||||
@ -45,11 +56,11 @@ static int ec_get_version(struct cros_ec_device *ec, char *str, int maxlen)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
msg->version = 0;
|
msg->version = 0;
|
||||||
msg->command = EC_CMD_GET_VERSION;
|
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
|
||||||
msg->insize = sizeof(*resp);
|
msg->insize = sizeof(*resp);
|
||||||
msg->outsize = 0;
|
msg->outsize = 0;
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -78,8 +89,10 @@ exit:
|
|||||||
/* Device file ops */
|
/* Device file ops */
|
||||||
static int ec_device_open(struct inode *inode, struct file *filp)
|
static int ec_device_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
filp->private_data = container_of(inode->i_cdev,
|
struct cros_ec_dev *ec = container_of(inode->i_cdev,
|
||||||
struct cros_ec_device, cdev);
|
struct cros_ec_dev, cdev);
|
||||||
|
filp->private_data = ec;
|
||||||
|
nonseekable_open(inode, filp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +104,7 @@ static int ec_device_release(struct inode *inode, struct file *filp)
|
|||||||
static ssize_t ec_device_read(struct file *filp, char __user *buffer,
|
static ssize_t ec_device_read(struct file *filp, char __user *buffer,
|
||||||
size_t length, loff_t *offset)
|
size_t length, loff_t *offset)
|
||||||
{
|
{
|
||||||
struct cros_ec_device *ec = filp->private_data;
|
struct cros_ec_dev *ec = filp->private_data;
|
||||||
char msg[sizeof(struct ec_response_get_version) +
|
char msg[sizeof(struct ec_response_get_version) +
|
||||||
sizeof(CROS_EC_DEV_VERSION)];
|
sizeof(CROS_EC_DEV_VERSION)];
|
||||||
size_t count;
|
size_t count;
|
||||||
@ -114,7 +127,7 @@ static ssize_t ec_device_read(struct file *filp, char __user *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ioctls */
|
/* Ioctls */
|
||||||
static long ec_device_ioctl_xcmd(struct cros_ec_device *ec, void __user *arg)
|
static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
|
||||||
{
|
{
|
||||||
long ret;
|
long ret;
|
||||||
struct cros_ec_command u_cmd;
|
struct cros_ec_command u_cmd;
|
||||||
@ -133,7 +146,8 @@ static long ec_device_ioctl_xcmd(struct cros_ec_device *ec, void __user *arg)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec, s_cmd);
|
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. */
|
/* Only copy data to userland if data was received. */
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -145,19 +159,21 @@ exit:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ec_device_ioctl_readmem(struct cros_ec_device *ec, void __user *arg)
|
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 = { };
|
struct cros_ec_readmem s_mem = { };
|
||||||
long num;
|
long num;
|
||||||
|
|
||||||
/* Not every platform supports direct reads */
|
/* Not every platform supports direct reads */
|
||||||
if (!ec->cmd_readmem)
|
if (!ec_dev->cmd_readmem)
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
|
|
||||||
if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
|
if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
num = ec->cmd_readmem(ec, s_mem.offset, s_mem.bytes, s_mem.buffer);
|
num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes,
|
||||||
|
s_mem.buffer);
|
||||||
if (num <= 0)
|
if (num <= 0)
|
||||||
return num;
|
return num;
|
||||||
|
|
||||||
@ -170,7 +186,7 @@ static long ec_device_ioctl_readmem(struct cros_ec_device *ec, void __user *arg)
|
|||||||
static long ec_device_ioctl(struct file *filp, unsigned int cmd,
|
static long ec_device_ioctl(struct file *filp, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
struct cros_ec_device *ec = filp->private_data;
|
struct cros_ec_dev *ec = filp->private_data;
|
||||||
|
|
||||||
if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
|
if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
@ -193,45 +209,81 @@ static const struct file_operations fops = {
|
|||||||
.unlocked_ioctl = ec_device_ioctl,
|
.unlocked_ioctl = ec_device_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void __remove(struct device *dev)
|
||||||
|
{
|
||||||
|
struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
|
||||||
|
class_dev);
|
||||||
|
kfree(ec);
|
||||||
|
}
|
||||||
|
|
||||||
static int ec_device_probe(struct platform_device *pdev)
|
static int ec_device_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
|
int retval = -ENOMEM;
|
||||||
int retval = -ENOTTY;
|
struct device *dev = &pdev->dev;
|
||||||
dev_t devno = MKDEV(ec_major, 0);
|
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
|
||||||
|
dev_t devno = MKDEV(ec_major, pdev->id);
|
||||||
|
struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
|
||||||
|
|
||||||
/* Instantiate it (and remember the EC) */
|
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;
|
||||||
|
device_initialize(&ec->class_dev);
|
||||||
cdev_init(&ec->cdev, &fops);
|
cdev_init(&ec->cdev, &fops);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the character device
|
||||||
|
* Link cdev to the class device to be sure device is not used
|
||||||
|
* before unbinding it.
|
||||||
|
*/
|
||||||
|
ec->cdev.kobj.parent = &ec->class_dev.kobj;
|
||||||
retval = cdev_add(&ec->cdev, devno, 1);
|
retval = cdev_add(&ec->cdev, devno, 1);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&pdev->dev, ": failed to add character device\n");
|
dev_err(dev, ": failed to add character device\n");
|
||||||
return retval;
|
goto cdev_add_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ec->vdev = device_create(cros_class, NULL, devno, ec,
|
/*
|
||||||
CROS_EC_DEV_NAME);
|
* Add the class device
|
||||||
if (IS_ERR(ec->vdev)) {
|
* Link to the character device for creating the /dev entry
|
||||||
retval = PTR_ERR(ec->vdev);
|
* in devtmpfs.
|
||||||
dev_err(&pdev->dev, ": failed to create device\n");
|
*/
|
||||||
cdev_del(&ec->cdev);
|
ec->class_dev.devt = ec->cdev.dev;
|
||||||
return retval;
|
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 set_named_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize extra interfaces */
|
retval = device_add(&ec->class_dev);
|
||||||
ec_dev_sysfs_init(ec);
|
if (retval) {
|
||||||
ec_dev_lightbar_init(ec);
|
dev_err(dev, "device_register failed => %d\n", retval);
|
||||||
|
goto dev_reg_failed;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
dev_reg_failed:
|
||||||
|
set_named_failed:
|
||||||
|
dev_set_drvdata(dev, NULL);
|
||||||
|
cdev_del(&ec->cdev);
|
||||||
|
cdev_add_failed:
|
||||||
|
kfree(ec);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ec_device_remove(struct platform_device *pdev)
|
static int ec_device_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
|
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
ec_dev_lightbar_remove(ec);
|
|
||||||
ec_dev_sysfs_remove(ec);
|
|
||||||
device_destroy(cros_class, MKDEV(ec_major, 0));
|
|
||||||
cdev_del(&ec->cdev);
|
cdev_del(&ec->cdev);
|
||||||
|
device_unregister(&ec->class_dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,10 +300,10 @@ static int __init cros_ec_dev_init(void)
|
|||||||
int ret;
|
int ret;
|
||||||
dev_t dev = 0;
|
dev_t dev = 0;
|
||||||
|
|
||||||
cros_class = class_create(THIS_MODULE, "chromeos");
|
ret = class_register(&cros_class);
|
||||||
if (IS_ERR(cros_class)) {
|
if (ret) {
|
||||||
pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
|
pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
|
||||||
return PTR_ERR(cros_class);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a range of minor numbers (starting with 0) to work with */
|
/* Get a range of minor numbers (starting with 0) to work with */
|
||||||
@ -273,7 +325,7 @@ static int __init cros_ec_dev_init(void)
|
|||||||
failed_devreg:
|
failed_devreg:
|
||||||
unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
|
unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
|
||||||
failed_chrdevreg:
|
failed_chrdevreg:
|
||||||
class_destroy(cros_class);
|
class_unregister(&cros_class);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +333,7 @@ static void __exit cros_ec_dev_exit(void)
|
|||||||
{
|
{
|
||||||
platform_driver_unregister(&cros_ec_dev_driver);
|
platform_driver_unregister(&cros_ec_dev_driver);
|
||||||
unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
|
unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
|
||||||
class_destroy(cros_class);
|
class_unregister(&cros_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(cros_ec_dev_init);
|
module_init(cros_ec_dev_init);
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
|
|
||||||
#define CROS_EC_DEV_NAME "cros_ec"
|
|
||||||
#define CROS_EC_DEV_VERSION "1.0.0"
|
#define CROS_EC_DEV_VERSION "1.0.0"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -44,10 +43,4 @@ struct cros_ec_readmem {
|
|||||||
#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
|
#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)
|
#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
|
||||||
|
|
||||||
void ec_dev_sysfs_init(struct cros_ec_device *);
|
|
||||||
void ec_dev_sysfs_remove(struct cros_ec_device *);
|
|
||||||
|
|
||||||
void ec_dev_lightbar_init(struct cros_ec_device *);
|
|
||||||
void ec_dev_lightbar_remove(struct cros_ec_device *);
|
|
||||||
|
|
||||||
#endif /* _CROS_EC_DEV_H_ */
|
#endif /* _CROS_EC_DEV_H_ */
|
||||||
|
@ -92,7 +92,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cros_ec_command *alloc_lightbar_cmd_msg(void)
|
static struct cros_ec_command *alloc_lightbar_cmd_msg(struct cros_ec_dev *ec)
|
||||||
{
|
{
|
||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
int len;
|
int len;
|
||||||
@ -105,14 +105,14 @@ static struct cros_ec_command *alloc_lightbar_cmd_msg(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
msg->version = 0;
|
msg->version = 0;
|
||||||
msg->command = EC_CMD_LIGHTBAR_CMD;
|
msg->command = EC_CMD_LIGHTBAR_CMD + ec->cmd_offset;
|
||||||
msg->outsize = sizeof(struct ec_params_lightbar);
|
msg->outsize = sizeof(struct ec_params_lightbar);
|
||||||
msg->insize = sizeof(struct ec_response_lightbar);
|
msg->insize = sizeof(struct ec_response_lightbar);
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_lightbar_version(struct cros_ec_device *ec,
|
static int get_lightbar_version(struct cros_ec_dev *ec,
|
||||||
uint32_t *ver_ptr, uint32_t *flg_ptr)
|
uint32_t *ver_ptr, uint32_t *flg_ptr)
|
||||||
{
|
{
|
||||||
struct ec_params_lightbar *param;
|
struct ec_params_lightbar *param;
|
||||||
@ -120,13 +120,13 @@ static int get_lightbar_version(struct cros_ec_device *ec,
|
|||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
msg = alloc_lightbar_cmd_msg();
|
msg = alloc_lightbar_cmd_msg(ec);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
param = (struct ec_params_lightbar *)msg->data;
|
param = (struct ec_params_lightbar *)msg->data;
|
||||||
param->cmd = LIGHTBAR_CMD_VERSION;
|
param->cmd = LIGHTBAR_CMD_VERSION;
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -165,7 +165,8 @@ static ssize_t version_show(struct device *dev,
|
|||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
uint32_t version = 0, flags = 0;
|
uint32_t version = 0, flags = 0;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = lb_throttle();
|
ret = lb_throttle();
|
||||||
@ -187,12 +188,13 @@ static ssize_t brightness_store(struct device *dev,
|
|||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
|
||||||
if (kstrtouint(buf, 0, &val))
|
if (kstrtouint(buf, 0, &val))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
msg = alloc_lightbar_cmd_msg();
|
msg = alloc_lightbar_cmd_msg(ec);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -203,7 +205,7 @@ static ssize_t brightness_store(struct device *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -231,11 +233,12 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
|
|||||||
{
|
{
|
||||||
struct ec_params_lightbar *param;
|
struct ec_params_lightbar *param;
|
||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
unsigned int val[4];
|
unsigned int val[4];
|
||||||
int ret, i = 0, j = 0, ok = 0;
|
int ret, i = 0, j = 0, ok = 0;
|
||||||
|
|
||||||
msg = alloc_lightbar_cmd_msg();
|
msg = alloc_lightbar_cmd_msg(ec);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -268,7 +271,7 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -304,9 +307,10 @@ static ssize_t sequence_show(struct device *dev,
|
|||||||
struct ec_response_lightbar *resp;
|
struct ec_response_lightbar *resp;
|
||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
int ret;
|
int ret;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
|
||||||
msg = alloc_lightbar_cmd_msg();
|
msg = alloc_lightbar_cmd_msg(ec);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -316,7 +320,7 @@ static ssize_t sequence_show(struct device *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -345,9 +349,10 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
|
|||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
int ret, len;
|
int ret, len;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
|
||||||
msg = alloc_lightbar_cmd_msg();
|
msg = alloc_lightbar_cmd_msg(ec);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -372,7 +377,7 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -397,25 +402,27 @@ static struct attribute *__lb_cmds_attrs[] = {
|
|||||||
&dev_attr_sequence.attr,
|
&dev_attr_sequence.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static struct attribute_group lb_cmds_attr_group = {
|
|
||||||
.name = "lightbar",
|
|
||||||
.attrs = __lb_cmds_attrs,
|
|
||||||
};
|
|
||||||
|
|
||||||
void ec_dev_lightbar_init(struct cros_ec_device *ec)
|
static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj,
|
||||||
|
struct attribute *a, int n)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
struct platform_device *pdev = container_of(ec->dev,
|
||||||
|
struct platform_device, dev);
|
||||||
|
if (pdev->id != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Only instantiate this stuff if the EC has a lightbar */
|
/* Only instantiate this stuff if the EC has a lightbar */
|
||||||
if (!get_lightbar_version(ec, NULL, NULL))
|
if (get_lightbar_version(ec, NULL, NULL))
|
||||||
return;
|
return a->mode;
|
||||||
|
else
|
||||||
ret = sysfs_create_group(&ec->vdev->kobj, &lb_cmds_attr_group);
|
return 0;
|
||||||
if (ret)
|
|
||||||
pr_warn("sysfs_create_group() failed: %d\n", ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ec_dev_lightbar_remove(struct cros_ec_device *ec)
|
struct attribute_group cros_ec_lightbar_attr_group = {
|
||||||
{
|
.name = "lightbar",
|
||||||
sysfs_remove_group(&ec->vdev->kobj, &lb_cmds_attr_group);
|
.attrs = __lb_cmds_attrs,
|
||||||
}
|
.is_visible = cros_ec_lightbar_attrs_are_visible,
|
||||||
|
};
|
||||||
|
@ -283,7 +283,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
platform_set_drvdata(pdev, ec_dev);
|
platform_set_drvdata(pdev, ec_dev);
|
||||||
ec_dev->dev = dev;
|
ec_dev->dev = dev;
|
||||||
ec_dev->ec_name = pdev->name;
|
|
||||||
ec_dev->phys_name = dev_name(dev);
|
ec_dev->phys_name = dev_name(dev);
|
||||||
ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
|
ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
|
||||||
ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
|
ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
|
||||||
|
@ -72,7 +72,8 @@ static ssize_t store_ec_reboot(struct device *dev,
|
|||||||
int got_cmd = 0, offset = 0;
|
int got_cmd = 0, offset = 0;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
|
||||||
msg = kmalloc(sizeof(*msg) + sizeof(*param), GFP_KERNEL);
|
msg = kmalloc(sizeof(*msg) + sizeof(*param), GFP_KERNEL);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
@ -112,10 +113,10 @@ static ssize_t store_ec_reboot(struct device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg->version = 0;
|
msg->version = 0;
|
||||||
msg->command = EC_CMD_REBOOT_EC;
|
msg->command = EC_CMD_REBOOT_EC + ec->cmd_offset;
|
||||||
msg->outsize = sizeof(*param);
|
msg->outsize = sizeof(*param);
|
||||||
msg->insize = 0;
|
msg->insize = 0;
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
count = ret;
|
count = ret;
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -139,7 +140,8 @@ static ssize_t show_ec_version(struct device *dev,
|
|||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
int ret;
|
int ret;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
|
||||||
msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
|
msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
@ -147,10 +149,10 @@ static ssize_t show_ec_version(struct device *dev,
|
|||||||
|
|
||||||
/* Get versions. RW may change. */
|
/* Get versions. RW may change. */
|
||||||
msg->version = 0;
|
msg->version = 0;
|
||||||
msg->command = EC_CMD_GET_VERSION;
|
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
|
||||||
msg->insize = sizeof(*r_ver);
|
msg->insize = sizeof(*r_ver);
|
||||||
msg->outsize = 0;
|
msg->outsize = 0;
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
count = ret;
|
count = ret;
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -175,9 +177,9 @@ static ssize_t show_ec_version(struct device *dev,
|
|||||||
image_names[r_ver->current_image] : "?"));
|
image_names[r_ver->current_image] : "?"));
|
||||||
|
|
||||||
/* Get build info. */
|
/* Get build info. */
|
||||||
msg->command = EC_CMD_GET_BUILD_INFO;
|
msg->command = EC_CMD_GET_BUILD_INFO + ec->cmd_offset;
|
||||||
msg->insize = EC_HOST_PARAM_SIZE;
|
msg->insize = EC_HOST_PARAM_SIZE;
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||||
"Build info: XFER ERROR %d\n", ret);
|
"Build info: XFER ERROR %d\n", ret);
|
||||||
@ -191,9 +193,9 @@ static ssize_t show_ec_version(struct device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get chip info. */
|
/* Get chip info. */
|
||||||
msg->command = EC_CMD_GET_CHIP_INFO;
|
msg->command = EC_CMD_GET_CHIP_INFO + ec->cmd_offset;
|
||||||
msg->insize = sizeof(*r_chip);
|
msg->insize = sizeof(*r_chip);
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||||
"Chip info: XFER ERROR %d\n", ret);
|
"Chip info: XFER ERROR %d\n", ret);
|
||||||
@ -215,9 +217,9 @@ static ssize_t show_ec_version(struct device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get board version */
|
/* Get board version */
|
||||||
msg->command = EC_CMD_GET_BOARD_VERSION;
|
msg->command = EC_CMD_GET_BOARD_VERSION + ec->cmd_offset;
|
||||||
msg->insize = sizeof(*r_board);
|
msg->insize = sizeof(*r_board);
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||||
"Board version: XFER ERROR %d\n", ret);
|
"Board version: XFER ERROR %d\n", ret);
|
||||||
@ -243,7 +245,8 @@ static ssize_t show_ec_flashinfo(struct device *dev,
|
|||||||
struct ec_response_flash_info *resp;
|
struct ec_response_flash_info *resp;
|
||||||
struct cros_ec_command *msg;
|
struct cros_ec_command *msg;
|
||||||
int ret;
|
int ret;
|
||||||
struct cros_ec_device *ec = dev_get_drvdata(dev);
|
struct cros_ec_dev *ec = container_of(dev,
|
||||||
|
struct cros_ec_dev, class_dev);
|
||||||
|
|
||||||
msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
|
msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
@ -251,10 +254,10 @@ static ssize_t show_ec_flashinfo(struct device *dev,
|
|||||||
|
|
||||||
/* The flash info shouldn't ever change, but ask each time anyway. */
|
/* The flash info shouldn't ever change, but ask each time anyway. */
|
||||||
msg->version = 0;
|
msg->version = 0;
|
||||||
msg->command = EC_CMD_FLASH_INFO;
|
msg->command = EC_CMD_FLASH_INFO + ec->cmd_offset;
|
||||||
msg->insize = sizeof(*resp);
|
msg->insize = sizeof(*resp);
|
||||||
msg->outsize = 0;
|
msg->outsize = 0;
|
||||||
ret = cros_ec_cmd_xfer(ec, msg);
|
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
if (msg->result != EC_RES_SUCCESS) {
|
if (msg->result != EC_RES_SUCCESS) {
|
||||||
@ -288,20 +291,7 @@ static struct attribute *__ec_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group ec_attr_group = {
|
struct attribute_group cros_ec_attr_group = {
|
||||||
.attrs = __ec_attrs,
|
.attrs = __ec_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
void ec_dev_sysfs_init(struct cros_ec_device *ec)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
error = sysfs_create_group(&ec->vdev->kobj, &ec_attr_group);
|
|
||||||
if (error)
|
|
||||||
pr_warn("failed to create group: %d\n", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ec_dev_sysfs_remove(struct cros_ec_device *ec)
|
|
||||||
{
|
|
||||||
sysfs_remove_group(&ec->vdev->kobj, &ec_attr_group);
|
|
||||||
}
|
|
||||||
|
@ -17,10 +17,14 @@
|
|||||||
#define __LINUX_MFD_CROS_EC_H
|
#define __LINUX_MFD_CROS_EC_H
|
||||||
|
|
||||||
#include <linux/cdev.h>
|
#include <linux/cdev.h>
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
#include <linux/mfd/cros_ec_commands.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
|
#define CROS_EC_DEV_NAME "cros_ec"
|
||||||
|
#define CROS_EC_DEV_PD_NAME "cros_pd"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The EC is unresponsive for a time after a reboot command. Add a
|
* The EC is unresponsive for a time after a reboot command. Add a
|
||||||
* simple delay to make sure that the bus stays locked.
|
* simple delay to make sure that the bus stays locked.
|
||||||
@ -71,11 +75,8 @@ struct cros_ec_command {
|
|||||||
/**
|
/**
|
||||||
* struct cros_ec_device - Information about a ChromeOS EC device
|
* struct cros_ec_device - Information about a ChromeOS EC device
|
||||||
*
|
*
|
||||||
* @ec_name: name of EC device (e.g. 'chromeos-ec')
|
|
||||||
* @phys_name: name of physical comms layer (e.g. 'i2c-4')
|
* @phys_name: name of physical comms layer (e.g. 'i2c-4')
|
||||||
* @dev: Device pointer for physical comms device
|
* @dev: Device pointer for physical comms device
|
||||||
* @vdev: Device pointer for virtual comms device
|
|
||||||
* @cdev: Character device structure for virtual comms device
|
|
||||||
* @was_wake_device: true if this device was set to wake the system from
|
* @was_wake_device: true if this device was set to wake the system from
|
||||||
* sleep at the last suspend
|
* sleep at the last suspend
|
||||||
* @cmd_readmem: direct read of the EC memory-mapped region, if supported
|
* @cmd_readmem: direct read of the EC memory-mapped region, if supported
|
||||||
@ -87,6 +88,7 @@ struct cros_ec_command {
|
|||||||
*
|
*
|
||||||
* @priv: Private data
|
* @priv: Private data
|
||||||
* @irq: Interrupt to use
|
* @irq: Interrupt to use
|
||||||
|
* @id: Device id
|
||||||
* @din: input buffer (for data from EC)
|
* @din: input buffer (for data from EC)
|
||||||
* @dout: output buffer (for data to EC)
|
* @dout: output buffer (for data to EC)
|
||||||
* \note
|
* \note
|
||||||
@ -109,11 +111,8 @@ struct cros_ec_command {
|
|||||||
struct cros_ec_device {
|
struct cros_ec_device {
|
||||||
|
|
||||||
/* These are used by other drivers that want to talk to the EC */
|
/* These are used by other drivers that want to talk to the EC */
|
||||||
const char *ec_name;
|
|
||||||
const char *phys_name;
|
const char *phys_name;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct device *vdev;
|
|
||||||
struct cdev cdev;
|
|
||||||
bool was_wake_device;
|
bool was_wake_device;
|
||||||
struct class *cros_class;
|
struct class *cros_class;
|
||||||
int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
|
int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
|
||||||
@ -138,6 +137,35 @@ struct cros_ec_device {
|
|||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* struct cros_ec_platform - ChromeOS EC platform information
|
||||||
|
*
|
||||||
|
* @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
|
||||||
|
* used in /dev/ and sysfs.
|
||||||
|
* @cmd_offset: offset to apply for each command. Set when
|
||||||
|
* registering a devicde behind another one.
|
||||||
|
*/
|
||||||
|
struct cros_ec_platform {
|
||||||
|
const char *ec_name;
|
||||||
|
u16 cmd_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct cros_ec_dev - ChromeOS EC device entry point
|
||||||
|
*
|
||||||
|
* @class_dev: Device structure used in sysfs
|
||||||
|
* @cdev: Character device structure in /dev
|
||||||
|
* @ec_dev: cros_ec_device structure to talk to the physical device
|
||||||
|
* @dev: pointer to the platform device
|
||||||
|
* @cmd_offset: offset to apply for each command.
|
||||||
|
*/
|
||||||
|
struct cros_ec_dev {
|
||||||
|
struct device class_dev;
|
||||||
|
struct cdev cdev;
|
||||||
|
struct cros_ec_device *ec_dev;
|
||||||
|
struct device *dev;
|
||||||
|
u16 cmd_offset;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cros_ec_suspend - Handle a suspend operation for the ChromeOS EC device
|
* cros_ec_suspend - Handle a suspend operation for the ChromeOS EC device
|
||||||
*
|
*
|
||||||
@ -224,4 +252,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev);
|
|||||||
*/
|
*/
|
||||||
int cros_ec_query_all(struct cros_ec_device *ec_dev);
|
int cros_ec_query_all(struct cros_ec_device *ec_dev);
|
||||||
|
|
||||||
|
/* sysfs stuff */
|
||||||
|
extern struct attribute_group cros_ec_attr_group;
|
||||||
|
extern struct attribute_group cros_ec_lightbar_attr_group;
|
||||||
|
|
||||||
#endif /* __LINUX_MFD_CROS_EC_H */
|
#endif /* __LINUX_MFD_CROS_EC_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user