mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-06 02:24:14 +08:00
Immutable branch between MFD, Extcon, HID, I2C, IIO, Input, Chrome, Power, PWM, RTC and Sounds due for the v5.4 merge window
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAl1s8HwACgkQUa+KL4f8 d2HpRg/5AeEuNE5EFEVNZcBingdBh7Cppj9EIsjuY3XRDAxVw/wXdI9uX3PKH9rD /lwhgMtLn+xZbL+ZBn5kzg7Q9XQ+4i7WHVUikWLJ/fZtE6rZQmilTnC8gX/10L7J /5Pj47GPTH/kUGvG/lHC+fWyfgzz6uIdUmo/FjaNAGNwduIqjQf9hIGrHMeKAzi+ /dOskN17I4R1HzMskGDG8ICfyyWeoHxxO9/UzZR9hDVV2dnPTGBAi+m7F/KJ4130 KZT9dy0bwyzcb2JEVWohUcXxqogWfra7q6k6xmGOMBEkQj8b3VLh0V1T1JrcPDpF 0bhRvZamolQdBNpXhH3NOWJQhfPKDwZJKa6jEktiOxkKt55/ai8Imxt3ITTlRlF8 SI4yvF6PoX+d12WarFf0RY+88eyt2HwkWhcVnjIAkgT+QthTvvjyTfD1mEdeV+N1 NWBjK5MmiyobTO2mz+1+9qznyGugpBgOuiU0l1WziAjDzhBo3srjkhXrkqcs9FRc cbcFwubxTqljW1hv3+mExztnIWPbtLfdbDdrP212YRsKaP1r1Gz2VEWzIP4/x5uU tsZr2frITnHumJ6CNNXZCMhDyY6X7EYRSM4u50bhVd5BUlths571grEsKAsN/yMl B3x8ynsN7Q5KrbHdbZagr0rd3HEoDlLkzBbpEdx7nijWtrT05HA= =UcyY -----END PGP SIGNATURE----- Merge tag 'ib-mfd-extcon-hid-i2c-iio-input-media-chrome-power-pwm-rtc-sound-v5.4' into chrome-platform/for-next Immutable branch between MFD, Extcon, HID, I2C, IIO, Input, Chrome, Power, PWM, RTC and Sound to allow picking patches that depends on the series that moves some code from the MFD subsystem to platform/chrome. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
This commit is contained in:
commit
7e0bb52d0d
@ -181,7 +181,7 @@ config EXTCON_USB_GPIO
|
||||
|
||||
config EXTCON_USBC_CROS_EC
|
||||
tristate "ChromeOS Embedded Controller EXTCON support"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
help
|
||||
Say Y here to enable USB Type C cable detection extcon support when
|
||||
using Chrome OS EC based USB Type-C ports.
|
||||
|
@ -6,10 +6,11 @@
|
||||
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
|
@ -376,7 +376,7 @@ config HOLTEK_FF
|
||||
|
||||
config HID_GOOGLE_HAMMER
|
||||
tristate "Google Hammer Keyboard"
|
||||
depends on USB_HID && LEDS_CLASS && MFD_CROS_EC
|
||||
depends on USB_HID && LEDS_CLASS && CROS_EC
|
||||
---help---
|
||||
Say Y here if you have a Google Hammer device.
|
||||
|
||||
|
@ -16,9 +16,9 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
@ -1345,7 +1345,7 @@ config I2C_SIBYTE
|
||||
|
||||
config I2C_CROS_EC_TUNNEL
|
||||
tristate "ChromeOS EC tunnel I2C bus"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
help
|
||||
If you say yes here you get an I2C bus that will tunnel i2c commands
|
||||
through to the other side of the ChromeOS EC to the i2c bus
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -18,9 +18,10 @@
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-accel-legacy"
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
config IIO_CROS_EC_SENSORS_CORE
|
||||
tristate "ChromeOS EC Sensors Core"
|
||||
depends on SYSFS && MFD_CROS_EC
|
||||
depends on SYSFS && CROS_EC
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
|
@ -20,9 +20,8 @@
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -17,8 +17,9 @@
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -14,9 +14,10 @@
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static char *cros_ec_loc[] = {
|
||||
|
@ -15,8 +15,9 @@
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -15,9 +15,10 @@
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/*
|
||||
|
@ -745,7 +745,7 @@ config KEYBOARD_W90P910
|
||||
config KEYBOARD_CROS_EC
|
||||
tristate "ChromeOS EC keyboard"
|
||||
select INPUT_MATRIXKMAP
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
help
|
||||
Say Y here to enable the matrix keyboard used by ChromeOS devices
|
||||
and implemented on the ChromeOS EC. You must enable one bus option
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -547,10 +547,9 @@ if CEC_PLATFORM_DRIVERS
|
||||
|
||||
config VIDEO_CROS_EC_CEC
|
||||
tristate "ChromeOS EC CEC driver"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
select CEC_CORE
|
||||
select CEC_NOTIFIER
|
||||
select CHROME_PLATFORMS
|
||||
select CROS_EC_PROTO
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
|
@ -14,10 +14,11 @@
|
||||
#include <linux/cec.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <media/cec.h>
|
||||
#include <media/cec-notifier.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-cec"
|
||||
|
||||
|
@ -211,26 +211,18 @@ config MFD_AXP20X_RSB
|
||||
components like regulators or the PEK (Power Enable Key) under the
|
||||
corresponding menus.
|
||||
|
||||
config MFD_CROS_EC
|
||||
tristate "ChromeOS Embedded Controller"
|
||||
config MFD_CROS_EC_DEV
|
||||
tristate "ChromeOS Embedded Controller multifunction device"
|
||||
select MFD_CORE
|
||||
select CHROME_PLATFORMS
|
||||
select CROS_EC_PROTO
|
||||
depends on X86 || ARM || ARM64 || COMPILE_TEST
|
||||
depends on CROS_EC
|
||||
default CROS_EC
|
||||
help
|
||||
If you say Y here you get support for the ChromeOS Embedded
|
||||
Controller (EC) providing keyboard, battery and power services.
|
||||
You also need to enable the driver for the bus you are using. The
|
||||
protocol for talking to the EC is defined by the bus driver.
|
||||
Select this to get support for ChromeOS Embedded Controller
|
||||
sub-devices. This driver will instantiate additional drivers such
|
||||
as RTC, USBPD, etc. but you have to select the individual drivers.
|
||||
|
||||
config MFD_CROS_EC_CHARDEV
|
||||
tristate "Chrome OS Embedded Controller userspace device interface"
|
||||
depends on MFD_CROS_EC
|
||||
---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.
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called cros-ec-dev.
|
||||
|
||||
config MFD_MADERA
|
||||
tristate "Cirrus Logic Madera codecs"
|
||||
|
@ -13,9 +13,7 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
|
||||
obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
|
||||
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
||||
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
||||
cros_ec_core-objs := cros_ec.o
|
||||
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o
|
||||
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
|
||||
|
||||
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
|
||||
|
@ -5,73 +5,112 @@
|
||||
* Copyright (C) 2014 Google, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/platform_data/cros_ec_chardev.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.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 struct class cros_class = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "chromeos",
|
||||
};
|
||||
|
||||
/* 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;
|
||||
/**
|
||||
* cros_feature_to_name - CrOS feature id to name/short description.
|
||||
* @id: The feature identifier.
|
||||
* @name: Device name associated with the feature id.
|
||||
* @desc: Short name that will be displayed.
|
||||
*/
|
||||
struct cros_feature_to_name {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
/**
|
||||
* cros_feature_to_cells - CrOS feature id to mfd cells association.
|
||||
* @id: The feature identifier.
|
||||
* @mfd_cells: Pointer to the array of mfd cells that needs to be added.
|
||||
* @num_cells: Number of mfd cells into the array.
|
||||
*/
|
||||
struct cros_feature_to_cells {
|
||||
unsigned int id;
|
||||
const struct mfd_cell *mfd_cells;
|
||||
unsigned int num_cells;
|
||||
};
|
||||
|
||||
msg->version = 0;
|
||||
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
|
||||
msg->insize = sizeof(*resp);
|
||||
msg->outsize = 0;
|
||||
static const struct cros_feature_to_name cros_mcu_devices[] = {
|
||||
{
|
||||
.id = EC_FEATURE_FINGERPRINT,
|
||||
.name = CROS_EC_DEV_FP_NAME,
|
||||
.desc = "Fingerprint",
|
||||
},
|
||||
{
|
||||
.id = EC_FEATURE_ISH,
|
||||
.name = CROS_EC_DEV_ISH_NAME,
|
||||
.desc = "Integrated Sensor Hub",
|
||||
},
|
||||
{
|
||||
.id = EC_FEATURE_SCP,
|
||||
.name = CROS_EC_DEV_SCP_NAME,
|
||||
.desc = "System Control Processor",
|
||||
},
|
||||
{
|
||||
.id = EC_FEATURE_TOUCHPAD,
|
||||
.name = CROS_EC_DEV_TP_NAME,
|
||||
.desc = "Touchpad",
|
||||
},
|
||||
};
|
||||
|
||||
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
static const struct mfd_cell cros_ec_cec_cells[] = {
|
||||
{ .name = "cros-ec-cec", },
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
static const struct mfd_cell cros_ec_rtc_cells[] = {
|
||||
{ .name = "cros-ec-rtc", },
|
||||
};
|
||||
|
||||
resp = (struct ec_response_get_version *)msg->data;
|
||||
if (resp->current_image >= ARRAY_SIZE(current_image_name))
|
||||
resp->current_image = 3; /* invalid */
|
||||
static const struct mfd_cell cros_usbpd_charger_cells[] = {
|
||||
{ .name = "cros-usbpd-charger", },
|
||||
{ .name = "cros-usbpd-logger", },
|
||||
};
|
||||
|
||||
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]);
|
||||
static const struct cros_feature_to_cells cros_subdevices[] = {
|
||||
{
|
||||
.id = EC_FEATURE_CEC,
|
||||
.mfd_cells = cros_ec_cec_cells,
|
||||
.num_cells = ARRAY_SIZE(cros_ec_cec_cells),
|
||||
},
|
||||
{
|
||||
.id = EC_FEATURE_RTC,
|
||||
.mfd_cells = cros_ec_rtc_cells,
|
||||
.num_cells = ARRAY_SIZE(cros_ec_rtc_cells),
|
||||
},
|
||||
{
|
||||
.id = EC_FEATURE_USB_PD,
|
||||
.mfd_cells = cros_usbpd_charger_cells,
|
||||
.num_cells = ARRAY_SIZE(cros_usbpd_charger_cells),
|
||||
},
|
||||
};
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
kfree(msg);
|
||||
return ret;
|
||||
}
|
||||
static const struct mfd_cell cros_ec_platform_cells[] = {
|
||||
{ .name = "cros-ec-chardev", },
|
||||
{ .name = "cros-ec-debugfs", },
|
||||
{ .name = "cros-ec-lightbar", },
|
||||
{ .name = "cros-ec-sysfs", },
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_vbc_cells[] = {
|
||||
{ .name = "cros-ec-vbc", }
|
||||
};
|
||||
|
||||
static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
|
||||
{
|
||||
@ -80,18 +119,15 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
|
||||
|
||||
if (ec->features[0] == -1U && ec->features[1] == -1U) {
|
||||
/* features bitmap not read yet */
|
||||
|
||||
msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
|
||||
msg = kzalloc(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) {
|
||||
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||
if (ret < 0) {
|
||||
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
|
||||
ret, msg->result);
|
||||
memset(ec->features, 0, sizeof(ec->features));
|
||||
@ -108,142 +144,6 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
|
||||
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 num;
|
||||
}
|
||||
|
||||
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 cros_ec_class_release(struct device *dev)
|
||||
{
|
||||
kfree(to_cros_ec_dev(dev));
|
||||
@ -276,8 +176,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
|
||||
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) {
|
||||
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||
if (ret < 0) {
|
||||
dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
|
||||
ret, msg->result);
|
||||
goto error;
|
||||
@ -304,8 +204,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
|
||||
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) {
|
||||
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||
if (ret < 0) {
|
||||
dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
|
||||
i, ret, msg->result);
|
||||
continue;
|
||||
@ -429,37 +329,12 @@ static void cros_ec_accel_legacy_register(struct cros_ec_dev *ec)
|
||||
* Register 2 accelerometers, we will fail in the IIO driver if there
|
||||
* are no sensors.
|
||||
*/
|
||||
ret = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_accel_legacy_cells,
|
||||
ARRAY_SIZE(cros_ec_accel_legacy_cells),
|
||||
NULL, 0, NULL);
|
||||
ret = mfd_add_hotplug_devices(ec->dev, cros_ec_accel_legacy_cells,
|
||||
ARRAY_SIZE(cros_ec_accel_legacy_cells));
|
||||
if (ret)
|
||||
dev_err(ec_dev->dev, "failed to add EC sensors\n");
|
||||
}
|
||||
|
||||
static const struct mfd_cell cros_ec_cec_cells[] = {
|
||||
{ .name = "cros-ec-cec" }
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_rtc_cells[] = {
|
||||
{ .name = "cros-ec-rtc" }
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_usbpd_charger_cells[] = {
|
||||
{ .name = "cros-usbpd-charger" },
|
||||
{ .name = "cros-usbpd-logger" },
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_platform_cells[] = {
|
||||
{ .name = "cros-ec-debugfs" },
|
||||
{ .name = "cros-ec-lightbar" },
|
||||
{ .name = "cros-ec-sysfs" },
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_vbc_cells[] = {
|
||||
{ .name = "cros-ec-vbc" }
|
||||
};
|
||||
|
||||
static int ec_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
int retval = -ENOMEM;
|
||||
@ -467,6 +342,7 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
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);
|
||||
int i;
|
||||
|
||||
if (!ec)
|
||||
return retval;
|
||||
@ -478,57 +354,27 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
ec->features[0] = -1U; /* Not cached yet */
|
||||
ec->features[1] = -1U; /* Not cached yet */
|
||||
device_initialize(&ec->class_dev);
|
||||
cdev_init(&ec->cdev, &fops);
|
||||
|
||||
/* Check whether this is actually a Fingerprint MCU rather than an EC */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_FINGERPRINT)) {
|
||||
dev_info(dev, "CrOS Fingerprint MCU detected.\n");
|
||||
for (i = 0; i < ARRAY_SIZE(cros_mcu_devices); i++) {
|
||||
/*
|
||||
* Help userspace differentiating ECs from FP MCU,
|
||||
* regardless of the probing order.
|
||||
* Check whether this is actually a dedicated MCU rather
|
||||
* than an standard EC.
|
||||
*/
|
||||
ec_platform->ec_name = CROS_EC_DEV_FP_NAME;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether this is actually an Integrated Sensor Hub (ISH)
|
||||
* rather than an EC.
|
||||
*/
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_ISH)) {
|
||||
dev_info(dev, "CrOS ISH MCU detected.\n");
|
||||
/*
|
||||
* Help userspace differentiating ECs from ISH MCU,
|
||||
* regardless of the probing order.
|
||||
*/
|
||||
ec_platform->ec_name = CROS_EC_DEV_ISH_NAME;
|
||||
}
|
||||
|
||||
/* Check whether this is actually a Touchpad MCU rather than an EC */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_TOUCHPAD)) {
|
||||
dev_info(dev, "CrOS Touchpad MCU detected.\n");
|
||||
/*
|
||||
* Help userspace differentiating ECs from TP MCU,
|
||||
* regardless of the probing order.
|
||||
*/
|
||||
ec_platform->ec_name = CROS_EC_DEV_TP_NAME;
|
||||
}
|
||||
|
||||
/* Check whether this is actually a SCP rather than an EC. */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_SCP)) {
|
||||
dev_info(dev, "CrOS SCP MCU detected.\n");
|
||||
/*
|
||||
* Help userspace differentiating ECs from SCP,
|
||||
* regardless of the probing order.
|
||||
*/
|
||||
ec_platform->ec_name = CROS_EC_DEV_SCP_NAME;
|
||||
if (cros_ec_check_features(ec, cros_mcu_devices[i].id)) {
|
||||
dev_info(dev, "CrOS %s MCU detected\n",
|
||||
cros_mcu_devices[i].desc);
|
||||
/*
|
||||
* Help userspace differentiating ECs from other MCU,
|
||||
* regardless of the probing order.
|
||||
*/
|
||||
ec_platform->ec_name = cros_mcu_devices[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = cros_ec_class_release;
|
||||
@ -539,6 +385,10 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
retval = device_add(&ec->class_dev);
|
||||
if (retval)
|
||||
goto failed;
|
||||
|
||||
/* check whether this EC is a sensor hub. */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
|
||||
cros_ec_sensors_register(ec);
|
||||
@ -546,53 +396,29 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
/* Workaroud for older EC firmware */
|
||||
cros_ec_accel_legacy_register(ec);
|
||||
|
||||
/* Check whether this EC instance has CEC host command support */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_cec_cells,
|
||||
ARRAY_SIZE(cros_ec_cec_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add cros-ec-cec device: %d\n",
|
||||
retval);
|
||||
/*
|
||||
* The following subdevices can be detected by sending the
|
||||
* EC_FEATURE_GET_CMD Embedded Controller device.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(cros_subdevices); i++) {
|
||||
if (cros_ec_check_features(ec, cros_subdevices[i].id)) {
|
||||
retval = mfd_add_hotplug_devices(ec->dev,
|
||||
cros_subdevices[i].mfd_cells,
|
||||
cros_subdevices[i].num_cells);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add %s subdevice: %d\n",
|
||||
cros_subdevices[i].mfd_cells->name,
|
||||
retval);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether this EC instance has RTC host command support */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_rtc_cells,
|
||||
ARRAY_SIZE(cros_ec_rtc_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add cros-ec-rtc device: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/* Check whether this EC instance has the PD charge manager */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_USB_PD)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_usbpd_charger_cells,
|
||||
ARRAY_SIZE(cros_usbpd_charger_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add cros-usbpd-charger device: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/* We can now add the sysfs class, we know which parameter to show */
|
||||
retval = cdev_device_add(&ec->cdev, &ec->class_dev);
|
||||
if (retval) {
|
||||
dev_err(dev, "cdev_device_add failed => %d\n", retval);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_platform_cells,
|
||||
ARRAY_SIZE(cros_ec_platform_cells),
|
||||
NULL, 0, NULL);
|
||||
/*
|
||||
* The following subdevices cannot be detected by sending the
|
||||
* EC_FEATURE_GET_CMD to the Embedded Controller device.
|
||||
*/
|
||||
retval = mfd_add_hotplug_devices(ec->dev, cros_ec_platform_cells,
|
||||
ARRAY_SIZE(cros_ec_platform_cells));
|
||||
if (retval)
|
||||
dev_warn(ec->dev,
|
||||
"failed to add cros-ec platform devices: %d\n",
|
||||
@ -601,10 +427,8 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
/* Check whether this EC instance has a VBC NVRAM */
|
||||
node = ec->ec_dev->dev->of_node;
|
||||
if (of_property_read_bool(node, "google,has-vbc-nvram")) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_vbc_cells,
|
||||
ARRAY_SIZE(cros_ec_vbc_cells),
|
||||
NULL, 0, NULL);
|
||||
retval = mfd_add_hotplug_devices(ec->dev, cros_ec_vbc_cells,
|
||||
ARRAY_SIZE(cros_ec_vbc_cells));
|
||||
if (retval)
|
||||
dev_warn(ec->dev, "failed to add VBC devices: %d\n",
|
||||
retval);
|
||||
@ -622,7 +446,6 @@ static int ec_device_remove(struct platform_device *pdev)
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
mfd_remove_devices(ec->dev);
|
||||
cdev_del(&ec->cdev);
|
||||
device_unregister(&ec->class_dev);
|
||||
return 0;
|
||||
}
|
||||
@ -645,7 +468,6 @@ static struct platform_driver cros_ec_dev_driver = {
|
||||
static int __init cros_ec_dev_init(void)
|
||||
{
|
||||
int ret;
|
||||
dev_t dev = 0;
|
||||
|
||||
ret = class_register(&cros_class);
|
||||
if (ret) {
|
||||
@ -653,14 +475,6 @@ static int __init cros_ec_dev_init(void)
|
||||
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) {
|
||||
@ -670,8 +484,6 @@ static int __init cros_ec_dev_init(void)
|
||||
return 0;
|
||||
|
||||
failed_devreg:
|
||||
unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
|
||||
failed_chrdevreg:
|
||||
class_unregister(&cros_class);
|
||||
return ret;
|
||||
}
|
||||
@ -679,7 +491,6 @@ failed_chrdevreg:
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,16 @@
|
||||
# Platform support for Chrome OS hardware (Chromebooks and Chromeboxes)
|
||||
#
|
||||
|
||||
config MFD_CROS_EC
|
||||
tristate "Platform support for Chrome hardware (transitional)"
|
||||
select CHROME_PLATFORMS
|
||||
select CROS_EC
|
||||
select CONFIG_MFD_CROS_EC_DEV
|
||||
depends on X86 || ARM || ARM64 || COMPILE_TEST
|
||||
help
|
||||
This is a transitional Kconfig option and will be removed after
|
||||
everyone enables the parts individually.
|
||||
|
||||
menuconfig CHROME_PLATFORMS
|
||||
bool "Platform support for Chrome hardware"
|
||||
depends on X86 || ARM || ARM64 || COMPILE_TEST
|
||||
@ -50,9 +60,22 @@ config CHROMEOS_TBMC
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called chromeos_tbmc.
|
||||
|
||||
config CROS_EC
|
||||
tristate "ChromeOS Embedded Controller"
|
||||
select CROS_EC_PROTO
|
||||
depends on X86 || ARM || ARM64 || COMPILE_TEST
|
||||
help
|
||||
If you say Y here you get support for the ChromeOS Embedded
|
||||
Controller (EC) providing keyboard, battery and power services.
|
||||
You also need to enable the driver for the bus you are using. The
|
||||
protocol for talking to the EC is defined by the bus driver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec.
|
||||
|
||||
config CROS_EC_I2C
|
||||
tristate "ChromeOS Embedded Controller (I2C)"
|
||||
depends on MFD_CROS_EC && I2C
|
||||
depends on CROS_EC && I2C
|
||||
|
||||
help
|
||||
If you say Y here, you get support for talking to the ChromeOS
|
||||
@ -62,7 +85,7 @@ config CROS_EC_I2C
|
||||
|
||||
config CROS_EC_RPMSG
|
||||
tristate "ChromeOS Embedded Controller (rpmsg)"
|
||||
depends on MFD_CROS_EC && RPMSG && OF
|
||||
depends on CROS_EC && RPMSG && OF
|
||||
help
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
through rpmsg. This uses a simple byte-level protocol with a
|
||||
@ -74,7 +97,7 @@ config CROS_EC_RPMSG
|
||||
|
||||
config CROS_EC_ISHTP
|
||||
tristate "ChromeOS Embedded Controller (ISHTP)"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
depends on INTEL_ISH_HID
|
||||
help
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
@ -87,7 +110,7 @@ config CROS_EC_ISHTP
|
||||
|
||||
config CROS_EC_SPI
|
||||
tristate "ChromeOS Embedded Controller (SPI)"
|
||||
depends on MFD_CROS_EC && SPI
|
||||
depends on CROS_EC && SPI
|
||||
|
||||
---help---
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
@ -97,7 +120,7 @@ config CROS_EC_SPI
|
||||
|
||||
config CROS_EC_LPC
|
||||
tristate "ChromeOS Embedded Controller (LPC)"
|
||||
depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
|
||||
depends on CROS_EC && ACPI && (X86 || COMPILE_TEST)
|
||||
help
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
over an LPC bus, including the LPC Microchip EC (MEC) variant.
|
||||
@ -123,10 +146,21 @@ config CROS_KBD_LED_BACKLIGHT
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_kbd_led_backlight.
|
||||
|
||||
config CROS_EC_CHARDEV
|
||||
tristate "ChromeOS EC miscdevice"
|
||||
depends on MFD_CROS_EC_DEV
|
||||
default MFD_CROS_EC_DEV
|
||||
help
|
||||
This driver adds file operations support to talk with the
|
||||
ChromeOS EC from userspace via a character device.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_chardev.
|
||||
|
||||
config CROS_EC_LIGHTBAR
|
||||
tristate "Chromebook Pixel's lightbar support"
|
||||
depends on MFD_CROS_EC_CHARDEV
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
depends on MFD_CROS_EC_DEV
|
||||
default MFD_CROS_EC_DEV
|
||||
help
|
||||
This option exposes the Chromebook Pixel's lightbar to
|
||||
userspace.
|
||||
@ -136,8 +170,8 @@ config CROS_EC_LIGHTBAR
|
||||
|
||||
config CROS_EC_VBC
|
||||
tristate "ChromeOS EC vboot context support"
|
||||
depends on MFD_CROS_EC_CHARDEV && OF
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
depends on MFD_CROS_EC_DEV && OF
|
||||
default MFD_CROS_EC_DEV
|
||||
help
|
||||
This option exposes the ChromeOS EC vboot context nvram to
|
||||
userspace.
|
||||
@ -147,8 +181,8 @@ config CROS_EC_VBC
|
||||
|
||||
config CROS_EC_DEBUGFS
|
||||
tristate "Export ChromeOS EC internals in DebugFS"
|
||||
depends on MFD_CROS_EC_CHARDEV && DEBUG_FS
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
depends on MFD_CROS_EC_DEV && DEBUG_FS
|
||||
default MFD_CROS_EC_DEV
|
||||
help
|
||||
This option exposes the ChromeOS EC device internals to
|
||||
userspace.
|
||||
@ -158,8 +192,8 @@ config CROS_EC_DEBUGFS
|
||||
|
||||
config CROS_EC_SYSFS
|
||||
tristate "ChromeOS EC control and information through sysfs"
|
||||
depends on MFD_CROS_EC_CHARDEV && SYSFS
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
depends on MFD_CROS_EC_DEV && SYSFS
|
||||
default MFD_CROS_EC_DEV
|
||||
help
|
||||
This option exposes some sysfs attributes to control and get
|
||||
information from ChromeOS EC.
|
||||
|
@ -6,6 +6,7 @@ CFLAGS_cros_ec_trace.o:= -I$(src)
|
||||
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
|
||||
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
|
||||
obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
|
||||
obj-$(CONFIG_CROS_EC) += cros_ec.o
|
||||
obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o
|
||||
obj-$(CONFIG_CROS_EC_RPMSG) += cros_ec_rpmsg.o
|
||||
@ -14,6 +15,7 @@ cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_mec.o
|
||||
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
|
||||
obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o
|
||||
obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o
|
||||
obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o
|
||||
obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
|
||||
obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
|
||||
obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
|
||||
|
@ -13,8 +13,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
@ -31,18 +31,6 @@ static struct cros_ec_platform pd_p = {
|
||||
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
|
||||
};
|
||||
|
||||
static const struct mfd_cell ec_cell = {
|
||||
.name = "cros-ec-dev",
|
||||
.platform_data = &ec_p,
|
||||
.pdata_size = sizeof(ec_p),
|
||||
};
|
||||
|
||||
static const struct mfd_cell ec_pd_cell = {
|
||||
.name = "cros-ec-dev",
|
||||
.platform_data = &pd_p,
|
||||
.pdata_size = sizeof(pd_p),
|
||||
};
|
||||
|
||||
static irqreturn_t ec_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = data;
|
||||
@ -154,38 +142,42 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||
}
|
||||
}
|
||||
|
||||
err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell,
|
||||
1, NULL, ec_dev->irq, NULL);
|
||||
if (err) {
|
||||
dev_err(dev,
|
||||
"Failed to register Embedded Controller subdevice %d\n",
|
||||
err);
|
||||
return err;
|
||||
/* Register a platform device for the main EC instance */
|
||||
ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev",
|
||||
PLATFORM_DEVID_AUTO, &ec_p,
|
||||
sizeof(struct cros_ec_platform));
|
||||
if (IS_ERR(ec_dev->ec)) {
|
||||
dev_err(ec_dev->dev,
|
||||
"Failed to create CrOS EC platform device\n");
|
||||
return PTR_ERR(ec_dev->ec);
|
||||
}
|
||||
|
||||
if (ec_dev->max_passthru) {
|
||||
/*
|
||||
* Register a PD device as well on top of this device.
|
||||
* Register a platform device for the PD behind the main EC.
|
||||
* 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.
|
||||
* sensor hub).
|
||||
*/
|
||||
err = devm_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;
|
||||
ec_dev->pd = platform_device_register_data(ec_dev->dev,
|
||||
"cros-ec-dev",
|
||||
PLATFORM_DEVID_AUTO, &pd_p,
|
||||
sizeof(struct cros_ec_platform));
|
||||
if (IS_ERR(ec_dev->pd)) {
|
||||
dev_err(ec_dev->dev,
|
||||
"Failed to create CrOS PD platform device\n");
|
||||
platform_device_unregister(ec_dev->ec);
|
||||
return PTR_ERR(ec_dev->pd);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
|
||||
err = devm_of_platform_populate(dev);
|
||||
if (err) {
|
||||
mfd_remove_devices(dev);
|
||||
platform_device_unregister(ec_dev->pd);
|
||||
platform_device_unregister(ec_dev->ec);
|
||||
dev_err(dev, "Failed to register sub-devices\n");
|
||||
return err;
|
||||
}
|
||||
@ -206,6 +198,16 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_register);
|
||||
|
||||
int cros_ec_unregister(struct cros_ec_device *ec_dev)
|
||||
{
|
||||
if (ec_dev->pd)
|
||||
platform_device_unregister(ec_dev->pd);
|
||||
platform_device_unregister(ec_dev->ec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_unregister);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int cros_ec_suspend(struct cros_ec_device *ec_dev)
|
||||
{
|
252
drivers/platform/chrome/cros_ec_chardev.c
Normal file
252
drivers/platform/chrome/cros_ec_chardev.c
Normal file
@ -0,0 +1,252 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Miscellaneous character driver for ChromeOS Embedded Controller
|
||||
*
|
||||
* Copyright 2014 Google, Inc.
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* This file is a rework and part of the code is ported from
|
||||
* drivers/mfd/cros_ec_dev.c that was originally written by
|
||||
* Bill Richardson.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_chardev.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-chardev"
|
||||
|
||||
struct chardev_data {
|
||||
struct cros_ec_dev *ec_dev;
|
||||
struct miscdevice misc;
|
||||
};
|
||||
|
||||
static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
|
||||
{
|
||||
static const char * const current_image_name[] = {
|
||||
"unknown", "read-only", "read-write", "invalid",
|
||||
};
|
||||
struct ec_response_get_version *resp;
|
||||
struct cros_ec_command *msg;
|
||||
int ret;
|
||||
|
||||
msg = kzalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
|
||||
msg->insize = sizeof(*resp);
|
||||
|
||||
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||
if (ret < 0) {
|
||||
snprintf(str, maxlen,
|
||||
"Unknown EC version, returned error: %d\n",
|
||||
msg->result);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device file ops
|
||||
*/
|
||||
static int cros_ec_chardev_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct miscdevice *mdev = filp->private_data;
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(mdev->parent);
|
||||
|
||||
filp->private_data = ec_dev;
|
||||
nonseekable_open(inode, filp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t cros_ec_chardev_read(struct file *filp, char __user *buffer,
|
||||
size_t length, loff_t *offset)
|
||||
{
|
||||
char msg[sizeof(struct ec_response_get_version) +
|
||||
sizeof(CROS_EC_DEV_VERSION)];
|
||||
struct cros_ec_dev *ec = filp->private_data;
|
||||
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 cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
|
||||
{
|
||||
struct cros_ec_command *s_cmd;
|
||||
struct cros_ec_command u_cmd;
|
||||
long ret;
|
||||
|
||||
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 cros_ec_chardev_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 num;
|
||||
}
|
||||
|
||||
static long cros_ec_chardev_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 cros_ec_chardev_ioctl_xcmd(ec, (void __user *)arg);
|
||||
case CROS_EC_DEV_IOCRDMEM:
|
||||
return cros_ec_chardev_ioctl_readmem(ec, (void __user *)arg);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static const struct file_operations chardev_fops = {
|
||||
.open = cros_ec_chardev_open,
|
||||
.read = cros_ec_chardev_read,
|
||||
.unlocked_ioctl = cros_ec_chardev_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = cros_ec_chardev_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int cros_ec_chardev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct cros_ec_platform *ec_platform = dev_get_platdata(ec_dev->dev);
|
||||
struct chardev_data *data;
|
||||
|
||||
/* Create a char device: we want to create it anew */
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->ec_dev = ec_dev;
|
||||
data->misc.minor = MISC_DYNAMIC_MINOR;
|
||||
data->misc.fops = &chardev_fops;
|
||||
data->misc.name = ec_platform->ec_name;
|
||||
data->misc.parent = pdev->dev.parent;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, data);
|
||||
|
||||
return misc_register(&data->misc);
|
||||
}
|
||||
|
||||
static int cros_ec_chardev_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct chardev_data *data = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
misc_deregister(&data->misc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cros_ec_chardev_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = cros_ec_chardev_probe,
|
||||
.remove = cros_ec_chardev_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(cros_ec_chardev_driver);
|
||||
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@collabora.com>");
|
||||
MODULE_DESCRIPTION("ChromeOS EC Miscellaneous Character Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -8,9 +8,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sched.h>
|
||||
|
@ -9,8 +9,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@ -307,6 +307,13 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
|
||||
|
||||
return cros_ec_unregister(ec_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int cros_ec_i2c_suspend(struct device *dev)
|
||||
{
|
||||
@ -357,6 +364,7 @@ static struct i2c_driver cros_ec_driver = {
|
||||
.pm = &cros_ec_i2c_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_i2c_probe,
|
||||
.remove = cros_ec_i2c_remove,
|
||||
.id_table = cros_ec_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -8,11 +8,10 @@
|
||||
// (ISH-TP).
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/intel-ish-client-if.h>
|
||||
|
||||
/*
|
||||
|
@ -9,8 +9,9 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -16,9 +16,9 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/suspend.h>
|
||||
@ -421,6 +421,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
|
||||
static int cros_ec_lpc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = platform_get_drvdata(pdev);
|
||||
struct acpi_device *adev;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
@ -428,7 +429,7 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
|
||||
acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
|
||||
cros_ec_lpc_acpi_notify);
|
||||
|
||||
return 0;
|
||||
return cros_ec_unregister(ec_dev);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
|
||||
|
@ -3,10 +3,11 @@
|
||||
//
|
||||
// Copyright (C) 2015 Google, Inc
|
||||
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rpmsg.h>
|
||||
#include <linux/slab.h>
|
||||
@ -233,6 +233,8 @@ static void cros_ec_rpmsg_remove(struct rpmsg_device *rpdev)
|
||||
struct cros_ec_device *ec_dev = dev_get_drvdata(&rpdev->dev);
|
||||
struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
|
||||
|
||||
cros_ec_unregister(ec_dev);
|
||||
|
||||
cancel_work_sync(&ec_rpmsg->host_event_work);
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
@ -785,6 +785,13 @@ static int cros_ec_spi_probe(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = spi_get_drvdata(spi);
|
||||
|
||||
return cros_ec_unregister(ec_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int cros_ec_spi_suspend(struct device *dev)
|
||||
{
|
||||
@ -823,6 +830,7 @@ static struct spi_driver cros_ec_driver_spi = {
|
||||
.pm = &cros_ec_spi_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_spi_probe,
|
||||
.remove = cros_ec_spi_remove,
|
||||
.id_table = cros_ec_spi_id,
|
||||
};
|
||||
|
||||
|
@ -9,8 +9,9 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define TRACE_SYMBOL(a) {a, #a}
|
||||
|
||||
// Generate the list using the following script:
|
||||
// sed -n 's/^#define \(EC_CMD_[[:alnum:]_]*\)\s.*/\tTRACE_SYMBOL(\1), \\/p' include/linux/mfd/cros_ec_commands.h
|
||||
// sed -n 's/^#define \(EC_CMD_[[:alnum:]_]*\)\s.*/\tTRACE_SYMBOL(\1), \\/p' include/linux/platform_data/cros_ec_commands.h
|
||||
#define EC_CMDS \
|
||||
TRACE_SYMBOL(EC_CMD_PROTO_VERSION), \
|
||||
TRACE_SYMBOL(EC_CMD_HELLO), \
|
||||
|
@ -11,8 +11,10 @@
|
||||
#if !defined(_CROS_EC_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _CROS_EC_TRACE_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
|
@ -7,8 +7,9 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-vbc"
|
||||
|
@ -6,10 +6,11 @@
|
||||
*/
|
||||
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
|
@ -670,7 +670,7 @@ config CHARGER_RT9455
|
||||
|
||||
config CHARGER_CROS_USBPD
|
||||
tristate "ChromeOS EC based USBPD charger"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
default n
|
||||
help
|
||||
Say Y here to enable ChromeOS EC based USBPD charger
|
||||
|
@ -5,9 +5,10 @@
|
||||
* Copyright (c) 2014 - 2018 Google, Inc
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -145,7 +145,7 @@ config PWM_CRC
|
||||
|
||||
config PWM_CROS_EC
|
||||
tristate "ChromeOS EC PWM driver"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
help
|
||||
PWM driver for exposing a PWM attached to the ChromeOS Embedded
|
||||
Controller.
|
||||
|
@ -6,8 +6,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -1274,7 +1274,7 @@ config RTC_DRV_ZYNQMP
|
||||
|
||||
config RTC_DRV_CROS_EC
|
||||
tristate "Chrome OS EC RTC driver"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
Chrome OS Embedded Controller's RTC.
|
||||
|
@ -6,8 +6,9 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -310,7 +310,6 @@ header-test- += linux/mfd/adp5520.h
|
||||
header-test- += linux/mfd/arizona/pdata.h
|
||||
header-test- += linux/mfd/as3711.h
|
||||
header-test- += linux/mfd/as3722.h
|
||||
header-test- += linux/mfd/cros_ec_commands.h
|
||||
header-test- += linux/mfd/da903x.h
|
||||
header-test- += linux/mfd/da9055/pdata.h
|
||||
header-test- += linux/mfd/da9063/pdata.h
|
||||
@ -480,6 +479,7 @@ header-test- += linux/platform_data/ata-pxa.h
|
||||
header-test- += linux/platform_data/atmel.h
|
||||
header-test- += linux/platform_data/bh1770glc.h
|
||||
header-test- += linux/platform_data/brcmfmac.h
|
||||
header-test- += linux/platform_data/cros_ec_commands.h
|
||||
header-test- += linux/platform_data/clk-u300.h
|
||||
header-test- += linux/platform_data/cyttsp4.h
|
||||
header-test- += linux/platform_data/dma-coh901318.h
|
||||
|
@ -10,7 +10,8 @@
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
|
||||
enum {
|
||||
CROS_EC_SENSOR_X,
|
||||
|
@ -8,183 +8,11 @@
|
||||
#ifndef __LINUX_MFD_CROS_EC_H
|
||||
#define __LINUX_MFD_CROS_EC_H
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define CROS_EC_DEV_NAME "cros_ec"
|
||||
#define CROS_EC_DEV_FP_NAME "cros_fp"
|
||||
#define CROS_EC_DEV_PD_NAME "cros_pd"
|
||||
#define CROS_EC_DEV_TP_NAME "cros_tp"
|
||||
#define CROS_EC_DEV_ISH_NAME "cros_ish"
|
||||
#define CROS_EC_DEV_SCP_NAME "cros_scp"
|
||||
|
||||
/*
|
||||
* The EC is unresponsive for a time after a reboot command. Add a
|
||||
* simple delay to make sure that the bus stays locked.
|
||||
*/
|
||||
#define EC_REBOOT_DELAY_MS 50
|
||||
|
||||
/*
|
||||
* Max bus-specific overhead incurred by request/responses.
|
||||
* I2C requires 1 additional byte for requests.
|
||||
* I2C requires 2 additional bytes for responses.
|
||||
* SPI requires up to 32 additional bytes for responses.
|
||||
*/
|
||||
#define EC_PROTO_VERSION_UNKNOWN 0
|
||||
#define EC_MAX_REQUEST_OVERHEAD 1
|
||||
#define EC_MAX_RESPONSE_OVERHEAD 32
|
||||
|
||||
/*
|
||||
* Command interface between EC and AP, for LPC, I2C and SPI interfaces.
|
||||
*/
|
||||
enum {
|
||||
EC_MSG_TX_HEADER_BYTES = 3,
|
||||
EC_MSG_TX_TRAILER_BYTES = 1,
|
||||
EC_MSG_TX_PROTO_BYTES = EC_MSG_TX_HEADER_BYTES +
|
||||
EC_MSG_TX_TRAILER_BYTES,
|
||||
EC_MSG_RX_PROTO_BYTES = 3,
|
||||
|
||||
/* Max length of messages for proto 2*/
|
||||
EC_PROTO2_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE +
|
||||
EC_MSG_TX_PROTO_BYTES,
|
||||
|
||||
EC_MAX_MSG_BYTES = 64 * 1024,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_ec_command - Information about a ChromeOS EC command.
|
||||
* @version: Command version number (often 0).
|
||||
* @command: Command to send (EC_CMD_...).
|
||||
* @outsize: Outgoing length in bytes.
|
||||
* @insize: Max number of bytes to accept from the EC.
|
||||
* @result: EC's response to the command (separate from communication failure).
|
||||
* @data: Where to put the incoming data from EC and outgoing data to EC.
|
||||
*/
|
||||
struct cros_ec_command {
|
||||
uint32_t version;
|
||||
uint32_t command;
|
||||
uint32_t outsize;
|
||||
uint32_t insize;
|
||||
uint32_t result;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_ec_device - Information about a ChromeOS EC device.
|
||||
* @phys_name: Name of physical comms layer (e.g. 'i2c-4').
|
||||
* @dev: Device pointer for physical comms device
|
||||
* @was_wake_device: True if this device was set to wake the system from
|
||||
* sleep at the last suspend.
|
||||
* @cros_class: The class structure for this device.
|
||||
* @cmd_readmem: Direct read of the EC memory-mapped region, if supported.
|
||||
* @offset: Is within EC_LPC_ADDR_MEMMAP region.
|
||||
* @bytes: Number of bytes to read. zero means "read a string" (including
|
||||
* the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be
|
||||
* read. Caller must ensure that the buffer is large enough for the
|
||||
* result when reading a string.
|
||||
* @max_request: Max size of message requested.
|
||||
* @max_response: Max size of message response.
|
||||
* @max_passthru: Max sice of passthru message.
|
||||
* @proto_version: The protocol version used for this device.
|
||||
* @priv: Private data.
|
||||
* @irq: Interrupt to use.
|
||||
* @id: Device id.
|
||||
* @din: Input buffer (for data from EC). This buffer will always be
|
||||
* dword-aligned and include enough space for up to 7 word-alignment
|
||||
* bytes also, so we can ensure that the body of the message is always
|
||||
* dword-aligned (64-bit). We use this alignment to keep ARM and x86
|
||||
* happy. Probably word alignment would be OK, there might be a small
|
||||
* performance advantage to using dword.
|
||||
* @dout: Output buffer (for data to EC). This buffer will always be
|
||||
* dword-aligned and include enough space for up to 7 word-alignment
|
||||
* bytes also, so we can ensure that the body of the message is always
|
||||
* dword-aligned (64-bit). We use this alignment to keep ARM and x86
|
||||
* happy. Probably word alignment would be OK, there might be a small
|
||||
* performance advantage to using dword.
|
||||
* @din_size: Size of din buffer to allocate (zero to use static din).
|
||||
* @dout_size: Size of dout buffer to allocate (zero to use static dout).
|
||||
* @wake_enabled: True if this device can wake the system from sleep.
|
||||
* @suspended: True if this device had been suspended.
|
||||
* @cmd_xfer: Send command to EC and get response.
|
||||
* Returns the number of bytes received if the communication
|
||||
* succeeded, but that doesn't mean the EC was happy with the
|
||||
* command. The caller should check msg.result for the EC's result
|
||||
* code.
|
||||
* @pkt_xfer: Send packet to EC and get response.
|
||||
* @lock: One transaction at a time.
|
||||
* @mkbp_event_supported: True if this EC supports the MKBP event protocol.
|
||||
* @host_sleep_v1: True if this EC supports the sleep v1 command.
|
||||
* @event_notifier: Interrupt event notifier for transport devices.
|
||||
* @event_data: Raw payload transferred with the MKBP event.
|
||||
* @event_size: Size in bytes of the event data.
|
||||
* @host_event_wake_mask: Mask of host events that cause wake from suspend.
|
||||
*/
|
||||
struct cros_ec_device {
|
||||
/* These are used by other drivers that want to talk to the EC */
|
||||
const char *phys_name;
|
||||
struct device *dev;
|
||||
bool was_wake_device;
|
||||
struct class *cros_class;
|
||||
int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
|
||||
unsigned int bytes, void *dest);
|
||||
|
||||
/* These are used to implement the platform-specific interface */
|
||||
u16 max_request;
|
||||
u16 max_response;
|
||||
u16 max_passthru;
|
||||
u16 proto_version;
|
||||
void *priv;
|
||||
int irq;
|
||||
u8 *din;
|
||||
u8 *dout;
|
||||
int din_size;
|
||||
int dout_size;
|
||||
bool wake_enabled;
|
||||
bool suspended;
|
||||
int (*cmd_xfer)(struct cros_ec_device *ec,
|
||||
struct cros_ec_command *msg);
|
||||
int (*pkt_xfer)(struct cros_ec_device *ec,
|
||||
struct cros_ec_command *msg);
|
||||
struct mutex lock;
|
||||
bool mkbp_event_supported;
|
||||
bool host_sleep_v1;
|
||||
struct blocking_notifier_head event_notifier;
|
||||
|
||||
struct ec_response_get_next_event_v1 event_data;
|
||||
int event_size;
|
||||
u32 host_event_wake_mask;
|
||||
u32 last_resume_result;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
|
||||
* @sensor_num: Id of the sensor, as reported by the EC.
|
||||
*/
|
||||
struct cros_ec_sensor_platform {
|
||||
u8 sensor_num;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 device behind another one.
|
||||
*/
|
||||
struct cros_ec_platform {
|
||||
const char *ec_name;
|
||||
u16 cmd_offset;
|
||||
};
|
||||
|
||||
struct cros_ec_debugfs;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @debug_info: cros_ec_debugfs structure for debugging information.
|
||||
@ -194,7 +22,6 @@ struct cros_ec_debugfs;
|
||||
*/
|
||||
struct cros_ec_dev {
|
||||
struct device class_dev;
|
||||
struct cdev cdev;
|
||||
struct cros_ec_device *ec_dev;
|
||||
struct device *dev;
|
||||
struct cros_ec_debugfs *debug_info;
|
||||
@ -205,123 +32,4 @@ struct cros_ec_dev {
|
||||
|
||||
#define to_cros_ec_dev(dev) container_of(dev, struct cros_ec_dev, class_dev)
|
||||
|
||||
/**
|
||||
* cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
|
||||
* @ec_dev: Device to suspend.
|
||||
*
|
||||
* This can be called by drivers to handle a suspend event.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_suspend(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
|
||||
* @ec_dev: Device to resume.
|
||||
*
|
||||
* This can be called by drivers to handle a resume event.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_resume(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
|
||||
* @ec_dev: Device to register.
|
||||
* @msg: Message to write.
|
||||
*
|
||||
* This is intended to be used by all ChromeOS EC drivers, but at present
|
||||
* only SPI uses it. Once LPC uses the same protocol it can start using it.
|
||||
* I2C could use it now, with a refactor of the existing code.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_check_result() - Check ec_msg->result.
|
||||
* @ec_dev: EC device.
|
||||
* @msg: Message to check.
|
||||
*
|
||||
* This is used by ChromeOS EC drivers to check the ec_msg->result for
|
||||
* errors and to warn about them.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_check_result(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
|
||||
* @ec_dev: EC device.
|
||||
* @msg: Message to write.
|
||||
*
|
||||
* Call this to send a command to the ChromeOS EC. This should be used
|
||||
* instead of calling the EC's cmd_xfer() callback directly.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
|
||||
* @ec_dev: EC device.
|
||||
* @msg: Message to write.
|
||||
*
|
||||
* This function is identical to cros_ec_cmd_xfer, except it returns success
|
||||
* status only if both the command was transmitted successfully and the EC
|
||||
* replied with success status. It's not necessary to check msg->result when
|
||||
* using this function.
|
||||
*
|
||||
* Return: The number of bytes transferred on success or negative error code.
|
||||
*/
|
||||
int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_register() - Register a new ChromeOS EC, using the provided info.
|
||||
* @ec_dev: Device to register.
|
||||
*
|
||||
* Before calling this, allocate a pointer to a new device and then fill
|
||||
* in all the fields up to the --private-- marker.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_register(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_query_all() - Query the protocol version supported by the
|
||||
* ChromeOS EC.
|
||||
* @ec_dev: Device to register.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_query_all(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
|
||||
* @ec_dev: Device to fetch event from.
|
||||
* @wake_event: Pointer to a bool set to true upon return if the event might be
|
||||
* treated as a wake event. Ignored if null.
|
||||
*
|
||||
* Return: negative error code on errors; 0 for no data; or else number of
|
||||
* bytes received (i.e., an event was retrieved successfully). Event types are
|
||||
* written out to @ec_dev->event_data.event_type on success.
|
||||
*/
|
||||
int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
|
||||
|
||||
/**
|
||||
* cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
|
||||
* @ec_dev: Device to fetch event from.
|
||||
*
|
||||
* When MKBP is supported, when the EC raises an interrupt, we collect the
|
||||
* events raised and call the functions in the ec notifier. This function
|
||||
* is a helper to know which events are raised.
|
||||
*
|
||||
* Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
|
||||
*/
|
||||
u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
|
||||
|
||||
#endif /* __LINUX_MFD_CROS_EC_H */
|
||||
|
@ -1,16 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* cros_ec_dev - expose the Chrome OS Embedded Controller to userspace
|
||||
* ChromeOS EC device interface.
|
||||
*
|
||||
* Copyright (C) 2014 Google, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _CROS_EC_DEV_H_
|
||||
#define _CROS_EC_DEV_H_
|
||||
#ifndef _UAPI_LINUX_CROS_EC_DEV_H_
|
||||
#define _UAPI_LINUX_CROS_EC_DEV_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
|
||||
#define CROS_EC_DEV_VERSION "1.0.0"
|
||||
|
319
include/linux/platform_data/cros_ec_proto.h
Normal file
319
include/linux/platform_data/cros_ec_proto.h
Normal file
@ -0,0 +1,319 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* ChromeOS Embedded Controller protocol interface.
|
||||
*
|
||||
* Copyright (C) 2012 Google, Inc
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_CROS_EC_PROTO_H
|
||||
#define __LINUX_CROS_EC_PROTO_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
|
||||
#define CROS_EC_DEV_NAME "cros_ec"
|
||||
#define CROS_EC_DEV_FP_NAME "cros_fp"
|
||||
#define CROS_EC_DEV_ISH_NAME "cros_ish"
|
||||
#define CROS_EC_DEV_PD_NAME "cros_pd"
|
||||
#define CROS_EC_DEV_SCP_NAME "cros_scp"
|
||||
#define CROS_EC_DEV_TP_NAME "cros_tp"
|
||||
|
||||
/*
|
||||
* The EC is unresponsive for a time after a reboot command. Add a
|
||||
* simple delay to make sure that the bus stays locked.
|
||||
*/
|
||||
#define EC_REBOOT_DELAY_MS 50
|
||||
|
||||
/*
|
||||
* Max bus-specific overhead incurred by request/responses.
|
||||
* I2C requires 1 additional byte for requests.
|
||||
* I2C requires 2 additional bytes for responses.
|
||||
* SPI requires up to 32 additional bytes for responses.
|
||||
*/
|
||||
#define EC_PROTO_VERSION_UNKNOWN 0
|
||||
#define EC_MAX_REQUEST_OVERHEAD 1
|
||||
#define EC_MAX_RESPONSE_OVERHEAD 32
|
||||
|
||||
/*
|
||||
* Command interface between EC and AP, for LPC, I2C and SPI interfaces.
|
||||
*/
|
||||
enum {
|
||||
EC_MSG_TX_HEADER_BYTES = 3,
|
||||
EC_MSG_TX_TRAILER_BYTES = 1,
|
||||
EC_MSG_TX_PROTO_BYTES = EC_MSG_TX_HEADER_BYTES +
|
||||
EC_MSG_TX_TRAILER_BYTES,
|
||||
EC_MSG_RX_PROTO_BYTES = 3,
|
||||
|
||||
/* Max length of messages for proto 2*/
|
||||
EC_PROTO2_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE +
|
||||
EC_MSG_TX_PROTO_BYTES,
|
||||
|
||||
EC_MAX_MSG_BYTES = 64 * 1024,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_ec_command - Information about a ChromeOS EC command.
|
||||
* @version: Command version number (often 0).
|
||||
* @command: Command to send (EC_CMD_...).
|
||||
* @outsize: Outgoing length in bytes.
|
||||
* @insize: Max number of bytes to accept from the EC.
|
||||
* @result: EC's response to the command (separate from communication failure).
|
||||
* @data: Where to put the incoming data from EC and outgoing data to EC.
|
||||
*/
|
||||
struct cros_ec_command {
|
||||
uint32_t version;
|
||||
uint32_t command;
|
||||
uint32_t outsize;
|
||||
uint32_t insize;
|
||||
uint32_t result;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_ec_device - Information about a ChromeOS EC device.
|
||||
* @phys_name: Name of physical comms layer (e.g. 'i2c-4').
|
||||
* @dev: Device pointer for physical comms device
|
||||
* @was_wake_device: True if this device was set to wake the system from
|
||||
* sleep at the last suspend.
|
||||
* @cros_class: The class structure for this device.
|
||||
* @cmd_readmem: Direct read of the EC memory-mapped region, if supported.
|
||||
* @offset: Is within EC_LPC_ADDR_MEMMAP region.
|
||||
* @bytes: Number of bytes to read. zero means "read a string" (including
|
||||
* the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be
|
||||
* read. Caller must ensure that the buffer is large enough for the
|
||||
* result when reading a string.
|
||||
* @max_request: Max size of message requested.
|
||||
* @max_response: Max size of message response.
|
||||
* @max_passthru: Max sice of passthru message.
|
||||
* @proto_version: The protocol version used for this device.
|
||||
* @priv: Private data.
|
||||
* @irq: Interrupt to use.
|
||||
* @id: Device id.
|
||||
* @din: Input buffer (for data from EC). This buffer will always be
|
||||
* dword-aligned and include enough space for up to 7 word-alignment
|
||||
* bytes also, so we can ensure that the body of the message is always
|
||||
* dword-aligned (64-bit). We use this alignment to keep ARM and x86
|
||||
* happy. Probably word alignment would be OK, there might be a small
|
||||
* performance advantage to using dword.
|
||||
* @dout: Output buffer (for data to EC). This buffer will always be
|
||||
* dword-aligned and include enough space for up to 7 word-alignment
|
||||
* bytes also, so we can ensure that the body of the message is always
|
||||
* dword-aligned (64-bit). We use this alignment to keep ARM and x86
|
||||
* happy. Probably word alignment would be OK, there might be a small
|
||||
* performance advantage to using dword.
|
||||
* @din_size: Size of din buffer to allocate (zero to use static din).
|
||||
* @dout_size: Size of dout buffer to allocate (zero to use static dout).
|
||||
* @wake_enabled: True if this device can wake the system from sleep.
|
||||
* @suspended: True if this device had been suspended.
|
||||
* @cmd_xfer: Send command to EC and get response.
|
||||
* Returns the number of bytes received if the communication
|
||||
* succeeded, but that doesn't mean the EC was happy with the
|
||||
* command. The caller should check msg.result for the EC's result
|
||||
* code.
|
||||
* @pkt_xfer: Send packet to EC and get response.
|
||||
* @lock: One transaction at a time.
|
||||
* @mkbp_event_supported: True if this EC supports the MKBP event protocol.
|
||||
* @host_sleep_v1: True if this EC supports the sleep v1 command.
|
||||
* @event_notifier: Interrupt event notifier for transport devices.
|
||||
* @event_data: Raw payload transferred with the MKBP event.
|
||||
* @event_size: Size in bytes of the event data.
|
||||
* @host_event_wake_mask: Mask of host events that cause wake from suspend.
|
||||
* @ec: The platform_device used by the mfd driver to interface with the
|
||||
* main EC.
|
||||
* @pd: The platform_device used by the mfd driver to interface with the
|
||||
* PD behind an EC.
|
||||
*/
|
||||
struct cros_ec_device {
|
||||
/* These are used by other drivers that want to talk to the EC */
|
||||
const char *phys_name;
|
||||
struct device *dev;
|
||||
bool was_wake_device;
|
||||
struct class *cros_class;
|
||||
int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
|
||||
unsigned int bytes, void *dest);
|
||||
|
||||
/* These are used to implement the platform-specific interface */
|
||||
u16 max_request;
|
||||
u16 max_response;
|
||||
u16 max_passthru;
|
||||
u16 proto_version;
|
||||
void *priv;
|
||||
int irq;
|
||||
u8 *din;
|
||||
u8 *dout;
|
||||
int din_size;
|
||||
int dout_size;
|
||||
bool wake_enabled;
|
||||
bool suspended;
|
||||
int (*cmd_xfer)(struct cros_ec_device *ec,
|
||||
struct cros_ec_command *msg);
|
||||
int (*pkt_xfer)(struct cros_ec_device *ec,
|
||||
struct cros_ec_command *msg);
|
||||
struct mutex lock;
|
||||
bool mkbp_event_supported;
|
||||
bool host_sleep_v1;
|
||||
struct blocking_notifier_head event_notifier;
|
||||
|
||||
struct ec_response_get_next_event_v1 event_data;
|
||||
int event_size;
|
||||
u32 host_event_wake_mask;
|
||||
u32 last_resume_result;
|
||||
|
||||
/* The platform devices used by the mfd driver */
|
||||
struct platform_device *ec;
|
||||
struct platform_device *pd;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
|
||||
* @sensor_num: Id of the sensor, as reported by the EC.
|
||||
*/
|
||||
struct cros_ec_sensor_platform {
|
||||
u8 sensor_num;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 device behind another one.
|
||||
*/
|
||||
struct cros_ec_platform {
|
||||
const char *ec_name;
|
||||
u16 cmd_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
|
||||
* @ec_dev: Device to suspend.
|
||||
*
|
||||
* This can be called by drivers to handle a suspend event.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_suspend(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
|
||||
* @ec_dev: Device to resume.
|
||||
*
|
||||
* This can be called by drivers to handle a resume event.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_resume(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
|
||||
* @ec_dev: Device to register.
|
||||
* @msg: Message to write.
|
||||
*
|
||||
* This is intended to be used by all ChromeOS EC drivers, but at present
|
||||
* only SPI uses it. Once LPC uses the same protocol it can start using it.
|
||||
* I2C could use it now, with a refactor of the existing code.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_check_result() - Check ec_msg->result.
|
||||
* @ec_dev: EC device.
|
||||
* @msg: Message to check.
|
||||
*
|
||||
* This is used by ChromeOS EC drivers to check the ec_msg->result for
|
||||
* errors and to warn about them.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_check_result(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
|
||||
* @ec_dev: EC device.
|
||||
* @msg: Message to write.
|
||||
*
|
||||
* Call this to send a command to the ChromeOS EC. This should be used
|
||||
* instead of calling the EC's cmd_xfer() callback directly.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
|
||||
* @ec_dev: EC device.
|
||||
* @msg: Message to write.
|
||||
*
|
||||
* This function is identical to cros_ec_cmd_xfer, except it returns success
|
||||
* status only if both the command was transmitted successfully and the EC
|
||||
* replied with success status. It's not necessary to check msg->result when
|
||||
* using this function.
|
||||
*
|
||||
* Return: The number of bytes transferred on success or negative error code.
|
||||
*/
|
||||
int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_register() - Register a new ChromeOS EC, using the provided info.
|
||||
* @ec_dev: Device to register.
|
||||
*
|
||||
* Before calling this, allocate a pointer to a new device and then fill
|
||||
* in all the fields up to the --private-- marker.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_register(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_unregister() - Remove a ChromeOS EC.
|
||||
* @ec_dev: Device to unregister.
|
||||
*
|
||||
* Call this to deregister a ChromeOS EC, then clean up any private data.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_unregister(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_query_all() - Query the protocol version supported by the
|
||||
* ChromeOS EC.
|
||||
* @ec_dev: Device to register.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_query_all(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
|
||||
* @ec_dev: Device to fetch event from.
|
||||
* @wake_event: Pointer to a bool set to true upon return if the event might be
|
||||
* treated as a wake event. Ignored if null.
|
||||
*
|
||||
* Return: negative error code on errors; 0 for no data; or else number of
|
||||
* bytes received (i.e., an event was retrieved successfully). Event types are
|
||||
* written out to @ec_dev->event_data.event_type on success.
|
||||
*/
|
||||
int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
|
||||
|
||||
/**
|
||||
* cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
|
||||
* @ec_dev: Device to fetch event from.
|
||||
*
|
||||
* When MKBP is supported, when the EC raises an interrupt, we collect the
|
||||
* events raised and call the functions in the ec notifier. This function
|
||||
* is a helper to know which events are raised.
|
||||
*
|
||||
* Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
|
||||
*/
|
||||
u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
|
||||
|
||||
#endif /* __LINUX_CROS_EC_PROTO_H */
|
@ -51,7 +51,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_BT_SCO
|
||||
select SND_SOC_BD28623
|
||||
select SND_SOC_CQ0093VC
|
||||
select SND_SOC_CROS_EC_CODEC if MFD_CROS_EC
|
||||
select SND_SOC_CROS_EC_CODEC if CROS_EC
|
||||
select SND_SOC_CS35L32 if I2C
|
||||
select SND_SOC_CS35L33 if I2C
|
||||
select SND_SOC_CS35L34 if I2C
|
||||
@ -474,7 +474,7 @@ config SND_SOC_CQ0093VC
|
||||
|
||||
config SND_SOC_CROS_EC_CODEC
|
||||
tristate "codec driver for ChromeOS EC"
|
||||
depends on MFD_CROS_EC
|
||||
depends on CROS_EC
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
ChromeOS Embedded Controller's Audio Codec.
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/cros_ec_commands.h>
|
||||
#include <linux/platform_data/cros_ec_proto.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
@ -99,7 +99,7 @@ config SND_SOC_MSM8996
|
||||
|
||||
config SND_SOC_SDM845
|
||||
tristate "SoC Machine driver for SDM845 boards"
|
||||
depends on QCOM_APR && MFD_CROS_EC && I2C
|
||||
depends on QCOM_APR && CROS_EC && I2C
|
||||
select SND_SOC_QDSP6
|
||||
select SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_RT5663
|
||||
|
Loading…
Reference in New Issue
Block a user