mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 07:30:54 +07:00
chrome platform changes for v5.4
* CrOS EC / MFD Migration - Move cros_ec core driver from mfd into chrome platform. * Wilco EC: - Add batt_ppid_info command to Wilco telemetry driver. * CrOS EC: - cros_ec_rpmsg : Add support to inform EC of suspend/resume status - cros_ec_rpmsg : Fix race condition on probe failed - cros_ec_chardev : Add a poll handler to receive MKBP events * Misc: - bugfixes in cros_usbpd_logger and cros_ec_ishtp -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQCtZK6p/AktxXfkOlzbaomhzOwwgUCXYKpygAKCRBzbaomhzOw wlkXAP9QCKia7LiNujIl9kh7WXSloxdO0BzL93pgSpNHfUDeSAD+Mlcp+54bDqkB WaF2SR14Z2vzAFafroQTl6m41xJTog4= =slD7 -----END PGP SIGNATURE----- Merge tag 'tag-chrome-platform-for-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux Pull chrome platform updates from Benson Leung: "CrOS EC / MFD Migration: - Move cros_ec core driver from mfd into chrome platform. Wilco EC: - Add batt_ppid_info command to Wilco telemetry driver. CrOS EC: - cros_ec_rpmsg : Add support to inform EC of suspend/resume status - cros_ec_rpmsg : Fix race condition on probe failed - cros_ec_chardev : Add a poll handler to receive MKBP events Misc: - bugfixes in cros_usbpd_logger and cros_ec_ishtp" * tag 'tag-chrome-platform-for-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux: platform/chrome: cros_usbpd_logger: null check create_singlethread_workqueue platform/chrome: cros_ec_chardev: Add a poll handler to receive MKBP events platform/chrome: cros_ec_rpmsg: Fix race with host command when probe failed platform/chrome: chromeos_tbmc: Report wake events mfd: cros_ec: Use mfd_add_hotplug_devices() helper mfd: cros_ec: Add convenience struct to define autodetectable CrOS EC subdevices mfd: cros_ec: Add convenience struct to define dedicated CrOS EC MCUs mfd: cros_ec: Use kzalloc and cros_ec_cmd_xfer_status helper mfd / platform: cros_ec: Reorganize platform and mfd includes mfd / platform: cros_ec: Rename config to a better name mfd: cros_ec: Switch to use the new cros-ec-chardev driver mfd / platform: cros_ec: Miscellaneous character device to talk with the EC mfd / platform: cros_ec: Move cros-ec core driver out from MFD mfd / platform: cros_ec: Handle chained ECs as platform devices platform/chrome: cros_ec_rpmsg: Add host command AP sleep state support platform/chrome: chromeos_laptop: drop checks of NULL-safe functions platform/chrome: wilco_ec: Add batt_ppid_info command to telemetry driver
This commit is contained in:
commit
32b90daf5c
@ -181,7 +181,7 @@ config EXTCON_USB_GPIO
|
|||||||
|
|
||||||
config EXTCON_USBC_CROS_EC
|
config EXTCON_USBC_CROS_EC
|
||||||
tristate "ChromeOS Embedded Controller EXTCON support"
|
tristate "ChromeOS Embedded Controller EXTCON support"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
help
|
help
|
||||||
Say Y here to enable USB Type C cable detection extcon support when
|
Say Y here to enable USB Type C cable detection extcon support when
|
||||||
using Chrome OS EC based USB Type-C ports.
|
using Chrome OS EC based USB Type-C ports.
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
|
|
||||||
#include <linux/extcon-provider.h>
|
#include <linux/extcon-provider.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/of.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/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
@ -376,7 +376,7 @@ config HOLTEK_FF
|
|||||||
|
|
||||||
config HID_GOOGLE_HAMMER
|
config HID_GOOGLE_HAMMER
|
||||||
tristate "Google Hammer Keyboard"
|
tristate "Google Hammer Keyboard"
|
||||||
depends on USB_HID && LEDS_CLASS && MFD_CROS_EC
|
depends on USB_HID && LEDS_CLASS && CROS_EC
|
||||||
---help---
|
---help---
|
||||||
Say Y here if you have a Google Hammer device.
|
Say Y here if you have a Google Hammer device.
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/hid.h>
|
#include <linux/hid.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/pm_wakeup.h>
|
#include <linux/pm_wakeup.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
@ -1345,7 +1345,7 @@ config I2C_SIBYTE
|
|||||||
|
|
||||||
config I2C_CROS_EC_TUNNEL
|
config I2C_CROS_EC_TUNNEL
|
||||||
tristate "ChromeOS EC tunnel I2C bus"
|
tristate "ChromeOS EC tunnel I2C bus"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
help
|
help
|
||||||
If you say yes here you get an I2C bus that will tunnel i2c commands
|
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
|
through to the other side of the ChromeOS EC to the i2c bus
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
#include <linux/platform_data/cros_ec_proto.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
#include <linux/iio/triggered_buffer.h>
|
#include <linux/iio/triggered_buffer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.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>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
#define DRV_NAME "cros-ec-accel-legacy"
|
#define DRV_NAME "cros-ec-accel-legacy"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
config IIO_CROS_EC_SENSORS_CORE
|
config IIO_CROS_EC_SENSORS_CORE
|
||||||
tristate "ChromeOS EC Sensors Core"
|
tristate "ChromeOS EC Sensors Core"
|
||||||
depends on SYSFS && MFD_CROS_EC
|
depends on SYSFS && CROS_EC
|
||||||
select IIO_BUFFER
|
select IIO_BUFFER
|
||||||
select IIO_TRIGGERED_BUFFER
|
select IIO_TRIGGERED_BUFFER
|
||||||
help
|
help
|
||||||
|
@ -20,9 +20,8 @@
|
|||||||
#include <linux/iio/triggered_buffer.h>
|
#include <linux/iio/triggered_buffer.h>
|
||||||
#include <linux/iio/trigger_consumer.h>
|
#include <linux/iio/trigger_consumer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
@ -17,8 +17,9 @@
|
|||||||
#include <linux/iio/triggered_buffer.h>
|
#include <linux/iio/triggered_buffer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
@ -14,9 +14,10 @@
|
|||||||
#include <linux/iio/trigger_consumer.h>
|
#include <linux/iio/trigger_consumer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.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>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
static char *cros_ec_loc[] = {
|
static char *cros_ec_loc[] = {
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
#include <linux/iio/trigger_consumer.h>
|
#include <linux/iio/trigger_consumer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
#include <linux/iio/trigger_consumer.h>
|
#include <linux/iio/trigger_consumer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.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>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -736,7 +736,7 @@ config KEYBOARD_XTKBD
|
|||||||
config KEYBOARD_CROS_EC
|
config KEYBOARD_CROS_EC
|
||||||
tristate "ChromeOS EC keyboard"
|
tristate "ChromeOS EC keyboard"
|
||||||
select INPUT_MATRIXKMAP
|
select INPUT_MATRIXKMAP
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
help
|
help
|
||||||
Say Y here to enable the matrix keyboard used by ChromeOS devices
|
Say Y here to enable the matrix keyboard used by ChromeOS devices
|
||||||
and implemented on the ChromeOS EC. You must enable one bus option
|
and implemented on the ChromeOS EC. You must enable one bus option
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/input/matrix_keypad.h>
|
#include <linux/input/matrix_keypad.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
#include <linux/platform_data/cros_ec_proto.h>
|
||||||
|
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
|
@ -547,10 +547,9 @@ if CEC_PLATFORM_DRIVERS
|
|||||||
|
|
||||||
config VIDEO_CROS_EC_CEC
|
config VIDEO_CROS_EC_CEC
|
||||||
tristate "ChromeOS EC CEC driver"
|
tristate "ChromeOS EC CEC driver"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
select CEC_CORE
|
select CEC_CORE
|
||||||
select CEC_NOTIFIER
|
select CEC_NOTIFIER
|
||||||
select CHROME_PLATFORMS
|
|
||||||
select CROS_EC_PROTO
|
select CROS_EC_PROTO
|
||||||
help
|
help
|
||||||
If you say yes here you will get support for the
|
If you say yes here you will get support for the
|
||||||
|
@ -14,10 +14,11 @@
|
|||||||
#include <linux/cec.h>
|
#include <linux/cec.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/interrupt.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.h>
|
||||||
#include <media/cec-notifier.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"
|
#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
|
components like regulators or the PEK (Power Enable Key) under the
|
||||||
corresponding menus.
|
corresponding menus.
|
||||||
|
|
||||||
config MFD_CROS_EC
|
config MFD_CROS_EC_DEV
|
||||||
tristate "ChromeOS Embedded Controller"
|
tristate "ChromeOS Embedded Controller multifunction device"
|
||||||
select MFD_CORE
|
select MFD_CORE
|
||||||
select CHROME_PLATFORMS
|
depends on CROS_EC
|
||||||
select CROS_EC_PROTO
|
default CROS_EC
|
||||||
depends on X86 || ARM || ARM64 || COMPILE_TEST
|
|
||||||
help
|
help
|
||||||
If you say Y here you get support for the ChromeOS Embedded
|
Select this to get support for ChromeOS Embedded Controller
|
||||||
Controller (EC) providing keyboard, battery and power services.
|
sub-devices. This driver will instantiate additional drivers such
|
||||||
You also need to enable the driver for the bus you are using. The
|
as RTC, USBPD, etc. but you have to select the individual drivers.
|
||||||
protocol for talking to the EC is defined by the bus driver.
|
|
||||||
|
|
||||||
config MFD_CROS_EC_CHARDEV
|
To compile this driver as a module, choose M here: the module will be
|
||||||
tristate "Chrome OS Embedded Controller userspace device interface"
|
called cros-ec-dev.
|
||||||
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.
|
|
||||||
|
|
||||||
config MFD_MADERA
|
config MFD_MADERA
|
||||||
tristate "Cirrus Logic Madera codecs"
|
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_ARCH_BCM2835) += bcm2835-pm.o
|
||||||
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
||||||
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
||||||
cros_ec_core-objs := cros_ec.o
|
obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o
|
||||||
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
|
|
||||||
obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
|
|
||||||
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
|
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
|
||||||
|
|
||||||
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
|
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
|
||||||
|
@ -5,73 +5,112 @@
|
|||||||
* Copyright (C) 2014 Google, Inc.
|
* Copyright (C) 2014 Google, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.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/slab.h>
|
||||||
#include <linux/uaccess.h>
|
|
||||||
|
|
||||||
#include "cros_ec_dev.h"
|
|
||||||
|
|
||||||
#define DRV_NAME "cros-ec-dev"
|
#define DRV_NAME "cros-ec-dev"
|
||||||
|
|
||||||
/* Device variables */
|
|
||||||
#define CROS_MAX_DEV 128
|
|
||||||
static int ec_major;
|
|
||||||
|
|
||||||
static struct class cros_class = {
|
static struct class cros_class = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "chromeos",
|
.name = "chromeos",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Basic communication */
|
/**
|
||||||
static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
|
* cros_feature_to_name - CrOS feature id to name/short description.
|
||||||
{
|
* @id: The feature identifier.
|
||||||
struct ec_response_get_version *resp;
|
* @name: Device name associated with the feature id.
|
||||||
static const char * const current_image_name[] = {
|
* @desc: Short name that will be displayed.
|
||||||
"unknown", "read-only", "read-write", "invalid",
|
*/
|
||||||
};
|
struct cros_feature_to_name {
|
||||||
struct cros_ec_command *msg;
|
unsigned int id;
|
||||||
int ret;
|
const char *name;
|
||||||
|
const char *desc;
|
||||||
|
};
|
||||||
|
|
||||||
msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
|
/**
|
||||||
if (!msg)
|
* cros_feature_to_cells - CrOS feature id to mfd cells association.
|
||||||
return -ENOMEM;
|
* @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;
|
static const struct cros_feature_to_name cros_mcu_devices[] = {
|
||||||
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
|
{
|
||||||
msg->insize = sizeof(*resp);
|
.id = EC_FEATURE_FINGERPRINT,
|
||||||
msg->outsize = 0;
|
.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);
|
static const struct mfd_cell cros_ec_cec_cells[] = {
|
||||||
if (ret < 0)
|
{ .name = "cros-ec-cec", },
|
||||||
goto exit;
|
};
|
||||||
|
|
||||||
if (msg->result != EC_RES_SUCCESS) {
|
static const struct mfd_cell cros_ec_rtc_cells[] = {
|
||||||
snprintf(str, maxlen,
|
{ .name = "cros-ec-rtc", },
|
||||||
"%s\nUnknown EC version: EC returned %d\n",
|
};
|
||||||
CROS_EC_DEV_VERSION, msg->result);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = (struct ec_response_get_version *)msg->data;
|
static const struct mfd_cell cros_usbpd_charger_cells[] = {
|
||||||
if (resp->current_image >= ARRAY_SIZE(current_image_name))
|
{ .name = "cros-usbpd-charger", },
|
||||||
resp->current_image = 3; /* invalid */
|
{ .name = "cros-usbpd-logger", },
|
||||||
|
};
|
||||||
|
|
||||||
snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION,
|
static const struct cros_feature_to_cells cros_subdevices[] = {
|
||||||
resp->version_string_ro, resp->version_string_rw,
|
{
|
||||||
current_image_name[resp->current_image]);
|
.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;
|
static const struct mfd_cell cros_ec_platform_cells[] = {
|
||||||
exit:
|
{ .name = "cros-ec-chardev", },
|
||||||
kfree(msg);
|
{ .name = "cros-ec-debugfs", },
|
||||||
return ret;
|
{ .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)
|
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) {
|
if (ec->features[0] == -1U && ec->features[1] == -1U) {
|
||||||
/* features bitmap not read yet */
|
/* features bitmap not read yet */
|
||||||
|
msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
|
||||||
msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
msg->version = 0;
|
|
||||||
msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
|
msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
|
||||||
msg->insize = sizeof(ec->features);
|
msg->insize = sizeof(ec->features);
|
||||||
msg->outsize = 0;
|
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||||
if (ret < 0 || msg->result != EC_RES_SUCCESS) {
|
if (ret < 0) {
|
||||||
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
|
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
|
||||||
ret, msg->result);
|
ret, msg->result);
|
||||||
memset(ec->features, 0, sizeof(ec->features));
|
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);
|
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)
|
static void cros_ec_class_release(struct device *dev)
|
||||||
{
|
{
|
||||||
kfree(to_cros_ec_dev(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 = (struct ec_params_motion_sense *)msg->data;
|
||||||
params->cmd = MOTIONSENSE_CMD_DUMP;
|
params->cmd = MOTIONSENSE_CMD_DUMP;
|
||||||
|
|
||||||
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||||
if (ret < 0 || msg->result != EC_RES_SUCCESS) {
|
if (ret < 0) {
|
||||||
dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
|
dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
|
||||||
ret, msg->result);
|
ret, msg->result);
|
||||||
goto error;
|
goto error;
|
||||||
@ -304,8 +204,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
|
|||||||
for (i = 0; i < sensor_num; i++) {
|
for (i = 0; i < sensor_num; i++) {
|
||||||
params->cmd = MOTIONSENSE_CMD_INFO;
|
params->cmd = MOTIONSENSE_CMD_INFO;
|
||||||
params->info.sensor_num = i;
|
params->info.sensor_num = i;
|
||||||
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
|
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
|
||||||
if (ret < 0 || msg->result != EC_RES_SUCCESS) {
|
if (ret < 0) {
|
||||||
dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
|
dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
|
||||||
i, ret, msg->result);
|
i, ret, msg->result);
|
||||||
continue;
|
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
|
* Register 2 accelerometers, we will fail in the IIO driver if there
|
||||||
* are no sensors.
|
* are no sensors.
|
||||||
*/
|
*/
|
||||||
ret = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
ret = mfd_add_hotplug_devices(ec->dev, cros_ec_accel_legacy_cells,
|
||||||
cros_ec_accel_legacy_cells,
|
ARRAY_SIZE(cros_ec_accel_legacy_cells));
|
||||||
ARRAY_SIZE(cros_ec_accel_legacy_cells),
|
|
||||||
NULL, 0, NULL);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(ec_dev->dev, "failed to add EC sensors\n");
|
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)
|
static int ec_device_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int retval = -ENOMEM;
|
int retval = -ENOMEM;
|
||||||
@ -467,6 +342,7 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
|
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
|
||||||
struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
|
struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!ec)
|
if (!ec)
|
||||||
return retval;
|
return retval;
|
||||||
@ -478,57 +354,27 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||||||
ec->features[0] = -1U; /* Not cached yet */
|
ec->features[0] = -1U; /* Not cached yet */
|
||||||
ec->features[1] = -1U; /* Not cached yet */
|
ec->features[1] = -1U; /* Not cached yet */
|
||||||
device_initialize(&ec->class_dev);
|
device_initialize(&ec->class_dev);
|
||||||
cdev_init(&ec->cdev, &fops);
|
|
||||||
|
|
||||||
/* Check whether this is actually a Fingerprint MCU rather than an EC */
|
for (i = 0; i < ARRAY_SIZE(cros_mcu_devices); i++) {
|
||||||
if (cros_ec_check_features(ec, EC_FEATURE_FINGERPRINT)) {
|
|
||||||
dev_info(dev, "CrOS Fingerprint MCU detected.\n");
|
|
||||||
/*
|
/*
|
||||||
* Help userspace differentiating ECs from FP MCU,
|
* Check whether this is actually a dedicated MCU rather
|
||||||
* regardless of the probing order.
|
* than an standard EC.
|
||||||
*/
|
*/
|
||||||
ec_platform->ec_name = CROS_EC_DEV_FP_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);
|
||||||
/*
|
/*
|
||||||
* Check whether this is actually an Integrated Sensor Hub (ISH)
|
* Help userspace differentiating ECs from other MCU,
|
||||||
* rather than an EC.
|
* regardless of the probing order.
|
||||||
*/
|
*/
|
||||||
if (cros_ec_check_features(ec, EC_FEATURE_ISH)) {
|
ec_platform->ec_name = cros_mcu_devices[i].name;
|
||||||
dev_info(dev, "CrOS ISH MCU detected.\n");
|
break;
|
||||||
/*
|
}
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the class device
|
* 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.class = &cros_class;
|
||||||
ec->class_dev.parent = dev;
|
ec->class_dev.parent = dev;
|
||||||
ec->class_dev.release = cros_ec_class_release;
|
ec->class_dev.release = cros_ec_class_release;
|
||||||
@ -539,6 +385,10 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retval = device_add(&ec->class_dev);
|
||||||
|
if (retval)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
/* check whether this EC is a sensor hub. */
|
/* check whether this EC is a sensor hub. */
|
||||||
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
|
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
|
||||||
cros_ec_sensors_register(ec);
|
cros_ec_sensors_register(ec);
|
||||||
@ -546,53 +396,29 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||||||
/* Workaroud for older EC firmware */
|
/* Workaroud for older EC firmware */
|
||||||
cros_ec_accel_legacy_register(ec);
|
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)) {
|
* The following subdevices can be detected by sending the
|
||||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
* EC_FEATURE_GET_CMD Embedded Controller device.
|
||||||
cros_ec_cec_cells,
|
*/
|
||||||
ARRAY_SIZE(cros_ec_cec_cells),
|
for (i = 0; i < ARRAY_SIZE(cros_subdevices); i++) {
|
||||||
NULL, 0, NULL);
|
if (cros_ec_check_features(ec, cros_subdevices[i].id)) {
|
||||||
if (retval)
|
retval = mfd_add_hotplug_devices(ec->dev,
|
||||||
dev_err(ec->dev,
|
cros_subdevices[i].mfd_cells,
|
||||||
"failed to add cros-ec-cec device: %d\n",
|
cros_subdevices[i].num_cells);
|
||||||
retval);
|
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)) {
|
* The following subdevices cannot be detected by sending the
|
||||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
* EC_FEATURE_GET_CMD to the Embedded Controller device.
|
||||||
cros_ec_rtc_cells,
|
*/
|
||||||
ARRAY_SIZE(cros_ec_rtc_cells),
|
retval = mfd_add_hotplug_devices(ec->dev, cros_ec_platform_cells,
|
||||||
NULL, 0, NULL);
|
ARRAY_SIZE(cros_ec_platform_cells));
|
||||||
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);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
dev_warn(ec->dev,
|
dev_warn(ec->dev,
|
||||||
"failed to add cros-ec platform devices: %d\n",
|
"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 */
|
/* Check whether this EC instance has a VBC NVRAM */
|
||||||
node = ec->ec_dev->dev->of_node;
|
node = ec->ec_dev->dev->of_node;
|
||||||
if (of_property_read_bool(node, "google,has-vbc-nvram")) {
|
if (of_property_read_bool(node, "google,has-vbc-nvram")) {
|
||||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
retval = mfd_add_hotplug_devices(ec->dev, cros_ec_vbc_cells,
|
||||||
cros_ec_vbc_cells,
|
ARRAY_SIZE(cros_ec_vbc_cells));
|
||||||
ARRAY_SIZE(cros_ec_vbc_cells),
|
|
||||||
NULL, 0, NULL);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
dev_warn(ec->dev, "failed to add VBC devices: %d\n",
|
dev_warn(ec->dev, "failed to add VBC devices: %d\n",
|
||||||
retval);
|
retval);
|
||||||
@ -622,7 +446,6 @@ static int ec_device_remove(struct platform_device *pdev)
|
|||||||
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
mfd_remove_devices(ec->dev);
|
mfd_remove_devices(ec->dev);
|
||||||
cdev_del(&ec->cdev);
|
|
||||||
device_unregister(&ec->class_dev);
|
device_unregister(&ec->class_dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -645,7 +468,6 @@ static struct platform_driver cros_ec_dev_driver = {
|
|||||||
static int __init cros_ec_dev_init(void)
|
static int __init cros_ec_dev_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
dev_t dev = 0;
|
|
||||||
|
|
||||||
ret = class_register(&cros_class);
|
ret = class_register(&cros_class);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -653,14 +475,6 @@ static int __init cros_ec_dev_init(void)
|
|||||||
return ret;
|
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 */
|
/* Register the driver */
|
||||||
ret = platform_driver_register(&cros_ec_dev_driver);
|
ret = platform_driver_register(&cros_ec_dev_driver);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -670,8 +484,6 @@ static int __init cros_ec_dev_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_devreg:
|
failed_devreg:
|
||||||
unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
|
|
||||||
failed_chrdevreg:
|
|
||||||
class_unregister(&cros_class);
|
class_unregister(&cros_class);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -679,7 +491,6 @@ static int __init cros_ec_dev_init(void)
|
|||||||
static void __exit cros_ec_dev_exit(void)
|
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);
|
|
||||||
class_unregister(&cros_class);
|
class_unregister(&cros_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
# Platform support for Chrome OS hardware (Chromebooks and Chromeboxes)
|
# 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
|
menuconfig CHROME_PLATFORMS
|
||||||
bool "Platform support for Chrome hardware"
|
bool "Platform support for Chrome hardware"
|
||||||
depends on X86 || ARM || ARM64 || COMPILE_TEST
|
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
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called chromeos_tbmc.
|
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
|
config CROS_EC_I2C
|
||||||
tristate "ChromeOS Embedded Controller (I2C)"
|
tristate "ChromeOS Embedded Controller (I2C)"
|
||||||
depends on MFD_CROS_EC && I2C
|
depends on CROS_EC && I2C
|
||||||
|
|
||||||
help
|
help
|
||||||
If you say Y here, you get support for talking to the ChromeOS
|
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
|
config CROS_EC_RPMSG
|
||||||
tristate "ChromeOS Embedded Controller (rpmsg)"
|
tristate "ChromeOS Embedded Controller (rpmsg)"
|
||||||
depends on MFD_CROS_EC && RPMSG && OF
|
depends on CROS_EC && RPMSG && OF
|
||||||
help
|
help
|
||||||
If you say Y here, you get support for talking to the ChromeOS EC
|
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
|
through rpmsg. This uses a simple byte-level protocol with a
|
||||||
@ -74,7 +97,7 @@ config CROS_EC_RPMSG
|
|||||||
|
|
||||||
config CROS_EC_ISHTP
|
config CROS_EC_ISHTP
|
||||||
tristate "ChromeOS Embedded Controller (ISHTP)"
|
tristate "ChromeOS Embedded Controller (ISHTP)"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
depends on INTEL_ISH_HID
|
depends on INTEL_ISH_HID
|
||||||
help
|
help
|
||||||
If you say Y here, you get support for talking to the ChromeOS EC
|
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
|
config CROS_EC_SPI
|
||||||
tristate "ChromeOS Embedded Controller (SPI)"
|
tristate "ChromeOS Embedded Controller (SPI)"
|
||||||
depends on MFD_CROS_EC && SPI
|
depends on CROS_EC && SPI
|
||||||
|
|
||||||
---help---
|
---help---
|
||||||
If you say Y here, you get support for talking to the ChromeOS EC
|
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
|
config CROS_EC_LPC
|
||||||
tristate "ChromeOS Embedded Controller (LPC)"
|
tristate "ChromeOS Embedded Controller (LPC)"
|
||||||
depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
|
depends on CROS_EC && ACPI && (X86 || COMPILE_TEST)
|
||||||
help
|
help
|
||||||
If you say Y here, you get support for talking to the ChromeOS EC
|
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.
|
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
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called cros_kbd_led_backlight.
|
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
|
config CROS_EC_LIGHTBAR
|
||||||
tristate "Chromebook Pixel's lightbar support"
|
tristate "Chromebook Pixel's lightbar support"
|
||||||
depends on MFD_CROS_EC_CHARDEV
|
depends on MFD_CROS_EC_DEV
|
||||||
default MFD_CROS_EC_CHARDEV
|
default MFD_CROS_EC_DEV
|
||||||
help
|
help
|
||||||
This option exposes the Chromebook Pixel's lightbar to
|
This option exposes the Chromebook Pixel's lightbar to
|
||||||
userspace.
|
userspace.
|
||||||
@ -136,8 +170,8 @@ config CROS_EC_LIGHTBAR
|
|||||||
|
|
||||||
config CROS_EC_VBC
|
config CROS_EC_VBC
|
||||||
tristate "ChromeOS EC vboot context support"
|
tristate "ChromeOS EC vboot context support"
|
||||||
depends on MFD_CROS_EC_CHARDEV && OF
|
depends on MFD_CROS_EC_DEV && OF
|
||||||
default MFD_CROS_EC_CHARDEV
|
default MFD_CROS_EC_DEV
|
||||||
help
|
help
|
||||||
This option exposes the ChromeOS EC vboot context nvram to
|
This option exposes the ChromeOS EC vboot context nvram to
|
||||||
userspace.
|
userspace.
|
||||||
@ -147,8 +181,8 @@ config CROS_EC_VBC
|
|||||||
|
|
||||||
config CROS_EC_DEBUGFS
|
config CROS_EC_DEBUGFS
|
||||||
tristate "Export ChromeOS EC internals in DebugFS"
|
tristate "Export ChromeOS EC internals in DebugFS"
|
||||||
depends on MFD_CROS_EC_CHARDEV && DEBUG_FS
|
depends on MFD_CROS_EC_DEV && DEBUG_FS
|
||||||
default MFD_CROS_EC_CHARDEV
|
default MFD_CROS_EC_DEV
|
||||||
help
|
help
|
||||||
This option exposes the ChromeOS EC device internals to
|
This option exposes the ChromeOS EC device internals to
|
||||||
userspace.
|
userspace.
|
||||||
@ -158,8 +192,8 @@ config CROS_EC_DEBUGFS
|
|||||||
|
|
||||||
config CROS_EC_SYSFS
|
config CROS_EC_SYSFS
|
||||||
tristate "ChromeOS EC control and information through sysfs"
|
tristate "ChromeOS EC control and information through sysfs"
|
||||||
depends on MFD_CROS_EC_CHARDEV && SYSFS
|
depends on MFD_CROS_EC_DEV && SYSFS
|
||||||
default MFD_CROS_EC_CHARDEV
|
default MFD_CROS_EC_DEV
|
||||||
help
|
help
|
||||||
This option exposes some sysfs attributes to control and get
|
This option exposes some sysfs attributes to control and get
|
||||||
information from ChromeOS EC.
|
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_LAPTOP) += chromeos_laptop.o
|
||||||
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
|
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
|
||||||
obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.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_I2C) += cros_ec_i2c.o
|
||||||
obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o
|
obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o
|
||||||
obj-$(CONFIG_CROS_EC_RPMSG) += cros_ec_rpmsg.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_LPC) += cros_ec_lpcs.o
|
||||||
obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.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_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_LIGHTBAR) += cros_ec_lightbar.o
|
||||||
obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
|
obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
|
||||||
obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
|
obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
|
||||||
|
@ -838,18 +838,14 @@ static void chromeos_laptop_destroy(const struct chromeos_laptop *cros_laptop)
|
|||||||
i2c_dev = &cros_laptop->i2c_peripherals[i];
|
i2c_dev = &cros_laptop->i2c_peripherals[i];
|
||||||
info = &i2c_dev->board_info;
|
info = &i2c_dev->board_info;
|
||||||
|
|
||||||
if (i2c_dev->client)
|
i2c_unregister_device(i2c_dev->client);
|
||||||
i2c_unregister_device(i2c_dev->client);
|
property_entries_free(info->properties);
|
||||||
|
|
||||||
if (info->properties)
|
|
||||||
property_entries_free(info->properties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
|
for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
|
||||||
acpi_dev = &cros_laptop->acpi_peripherals[i];
|
acpi_dev = &cros_laptop->acpi_peripherals[i];
|
||||||
|
|
||||||
if (acpi_dev->properties)
|
property_entries_free(acpi_dev->properties);
|
||||||
property_entries_free(acpi_dev->properties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(cros_laptop->i2c_peripherals);
|
kfree(cros_laptop->i2c_peripherals);
|
||||||
|
@ -47,6 +47,7 @@ static __maybe_unused int chromeos_tbmc_resume(struct device *dev)
|
|||||||
|
|
||||||
static void chromeos_tbmc_notify(struct acpi_device *adev, u32 event)
|
static void chromeos_tbmc_notify(struct acpi_device *adev, u32 event)
|
||||||
{
|
{
|
||||||
|
acpi_pm_wakeup_event(&adev->dev);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case 0x80:
|
case 0x80:
|
||||||
chromeos_tbmc_query_switch(adev, adev->driver_data);
|
chromeos_tbmc_query_switch(adev, adev->driver_data);
|
||||||
@ -90,6 +91,7 @@ static int chromeos_tbmc_add(struct acpi_device *adev)
|
|||||||
dev_err(dev, "cannot register input device\n");
|
dev_err(dev, "cannot register input device\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
device_init_wakeup(dev, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/platform_data/cros_ec_proto.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <asm/unaligned.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),
|
.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)
|
static irqreturn_t ec_irq_thread(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct cros_ec_device *ec_dev = 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,
|
/* Register a platform device for the main EC instance */
|
||||||
1, NULL, ec_dev->irq, NULL);
|
ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev",
|
||||||
if (err) {
|
PLATFORM_DEVID_AUTO, &ec_p,
|
||||||
dev_err(dev,
|
sizeof(struct cros_ec_platform));
|
||||||
"Failed to register Embedded Controller subdevice %d\n",
|
if (IS_ERR(ec_dev->ec)) {
|
||||||
err);
|
dev_err(ec_dev->dev,
|
||||||
return err;
|
"Failed to create CrOS EC platform device\n");
|
||||||
|
return PTR_ERR(ec_dev->ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ec_dev->max_passthru) {
|
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:
|
* We make the following assumptions:
|
||||||
* - behind an EC, we have a pd
|
* - behind an EC, we have a pd
|
||||||
* - only one device added.
|
* - only one device added.
|
||||||
* - the EC is responsive at init time (it is not true for a
|
* - 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_dev->pd = platform_device_register_data(ec_dev->dev,
|
||||||
&ec_pd_cell, 1, NULL, ec_dev->irq, NULL);
|
"cros-ec-dev",
|
||||||
if (err) {
|
PLATFORM_DEVID_AUTO, &pd_p,
|
||||||
dev_err(dev,
|
sizeof(struct cros_ec_platform));
|
||||||
"Failed to register Power Delivery subdevice %d\n",
|
if (IS_ERR(ec_dev->pd)) {
|
||||||
err);
|
dev_err(ec_dev->dev,
|
||||||
return err;
|
"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) {
|
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
|
||||||
err = devm_of_platform_populate(dev);
|
err = devm_of_platform_populate(dev);
|
||||||
if (err) {
|
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");
|
dev_err(dev, "Failed to register sub-devices\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -206,6 +198,16 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cros_ec_register);
|
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
|
#ifdef CONFIG_PM_SLEEP
|
||||||
int cros_ec_suspend(struct cros_ec_device *ec_dev)
|
int cros_ec_suspend(struct cros_ec_device *ec_dev)
|
||||||
{
|
{
|
419
drivers/platform/chrome/cros_ec_chardev.c
Normal file
419
drivers/platform/chrome/cros_ec_chardev.c
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
// 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/notifier.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/poll.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#define DRV_NAME "cros-ec-chardev"
|
||||||
|
|
||||||
|
/* Arbitrary bounded size for the event queue */
|
||||||
|
#define CROS_MAX_EVENT_LEN PAGE_SIZE
|
||||||
|
|
||||||
|
struct chardev_data {
|
||||||
|
struct cros_ec_dev *ec_dev;
|
||||||
|
struct miscdevice misc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chardev_priv {
|
||||||
|
struct cros_ec_dev *ec_dev;
|
||||||
|
struct notifier_block notifier;
|
||||||
|
wait_queue_head_t wait_event;
|
||||||
|
unsigned long event_mask;
|
||||||
|
struct list_head events;
|
||||||
|
size_t event_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ec_event {
|
||||||
|
struct list_head node;
|
||||||
|
size_t size;
|
||||||
|
u8 event_type;
|
||||||
|
u8 data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cros_ec_chardev_mkbp_event(struct notifier_block *nb,
|
||||||
|
unsigned long queued_during_suspend,
|
||||||
|
void *_notify)
|
||||||
|
{
|
||||||
|
struct chardev_priv *priv = container_of(nb, struct chardev_priv,
|
||||||
|
notifier);
|
||||||
|
struct cros_ec_device *ec_dev = priv->ec_dev->ec_dev;
|
||||||
|
struct ec_event *event;
|
||||||
|
unsigned long event_bit = 1 << ec_dev->event_data.event_type;
|
||||||
|
int total_size = sizeof(*event) + ec_dev->event_size;
|
||||||
|
|
||||||
|
if (!(event_bit & priv->event_mask) ||
|
||||||
|
(priv->event_len + total_size) > CROS_MAX_EVENT_LEN)
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
|
event = kzalloc(total_size, GFP_KERNEL);
|
||||||
|
if (!event)
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
|
event->size = ec_dev->event_size;
|
||||||
|
event->event_type = ec_dev->event_data.event_type;
|
||||||
|
memcpy(event->data, &ec_dev->event_data.data, ec_dev->event_size);
|
||||||
|
|
||||||
|
spin_lock(&priv->wait_event.lock);
|
||||||
|
list_add_tail(&event->node, &priv->events);
|
||||||
|
priv->event_len += total_size;
|
||||||
|
wake_up_locked(&priv->wait_event);
|
||||||
|
spin_unlock(&priv->wait_event.lock);
|
||||||
|
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ec_event *cros_ec_chardev_fetch_event(struct chardev_priv *priv,
|
||||||
|
bool fetch, bool block)
|
||||||
|
{
|
||||||
|
struct ec_event *event;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
spin_lock(&priv->wait_event.lock);
|
||||||
|
if (!block && list_empty(&priv->events)) {
|
||||||
|
event = ERR_PTR(-EWOULDBLOCK);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fetch) {
|
||||||
|
event = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = wait_event_interruptible_locked(priv->wait_event,
|
||||||
|
!list_empty(&priv->events));
|
||||||
|
if (err) {
|
||||||
|
event = ERR_PTR(err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
event = list_first_entry(&priv->events, struct ec_event, node);
|
||||||
|
list_del(&event->node);
|
||||||
|
priv->event_len -= sizeof(*event) + event->size;
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock(&priv->wait_event.lock);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
struct chardev_priv *priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
priv->ec_dev = ec_dev;
|
||||||
|
filp->private_data = priv;
|
||||||
|
INIT_LIST_HEAD(&priv->events);
|
||||||
|
init_waitqueue_head(&priv->wait_event);
|
||||||
|
nonseekable_open(inode, filp);
|
||||||
|
|
||||||
|
priv->notifier.notifier_call = cros_ec_chardev_mkbp_event;
|
||||||
|
ret = blocking_notifier_chain_register(&ec_dev->ec_dev->event_notifier,
|
||||||
|
&priv->notifier);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(ec_dev->dev, "failed to register event notifier\n");
|
||||||
|
kfree(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __poll_t cros_ec_chardev_poll(struct file *filp, poll_table *wait)
|
||||||
|
{
|
||||||
|
struct chardev_priv *priv = filp->private_data;
|
||||||
|
|
||||||
|
poll_wait(filp, &priv->wait_event, wait);
|
||||||
|
|
||||||
|
if (list_empty(&priv->events))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return EPOLLIN | EPOLLRDNORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 chardev_priv *priv = filp->private_data;
|
||||||
|
struct cros_ec_dev *ec_dev = priv->ec_dev;
|
||||||
|
size_t count;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (priv->event_mask) { /* queued MKBP event */
|
||||||
|
struct ec_event *event;
|
||||||
|
|
||||||
|
event = cros_ec_chardev_fetch_event(priv, length != 0,
|
||||||
|
!(filp->f_flags & O_NONBLOCK));
|
||||||
|
if (IS_ERR(event))
|
||||||
|
return PTR_ERR(event);
|
||||||
|
/*
|
||||||
|
* length == 0 is special - no IO is done but we check
|
||||||
|
* for error conditions.
|
||||||
|
*/
|
||||||
|
if (length == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* The event is 1 byte of type plus the payload */
|
||||||
|
count = min(length, event->size + 1);
|
||||||
|
ret = copy_to_user(buffer, &event->event_type, count);
|
||||||
|
kfree(event);
|
||||||
|
if (ret) /* the copy failed */
|
||||||
|
return -EFAULT;
|
||||||
|
*offset = count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Legacy behavior if no event mask is defined
|
||||||
|
*/
|
||||||
|
if (*offset != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = ec_get_version(ec_dev, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cros_ec_chardev_release(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
struct chardev_priv *priv = filp->private_data;
|
||||||
|
struct cros_ec_dev *ec_dev = priv->ec_dev;
|
||||||
|
struct ec_event *event, *e;
|
||||||
|
|
||||||
|
blocking_notifier_chain_unregister(&ec_dev->ec_dev->event_notifier,
|
||||||
|
&priv->notifier);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(event, e, &priv->events, node) {
|
||||||
|
list_del(&event->node);
|
||||||
|
kfree(event);
|
||||||
|
}
|
||||||
|
kfree(priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 chardev_priv *priv = filp->private_data;
|
||||||
|
struct cros_ec_dev *ec = priv->ec_dev;
|
||||||
|
|
||||||
|
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);
|
||||||
|
case CROS_EC_DEV_IOCEVENTMASK:
|
||||||
|
priv->event_mask = arg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations chardev_fops = {
|
||||||
|
.open = cros_ec_chardev_open,
|
||||||
|
.poll = cros_ec_chardev_poll,
|
||||||
|
.read = cros_ec_chardev_read,
|
||||||
|
.release = cros_ec_chardev_release,
|
||||||
|
.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/delay.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.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/platform_device.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
#include <linux/platform_data/cros_ec_proto.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
@ -307,6 +307,13 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
|
|||||||
return 0;
|
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
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int cros_ec_i2c_suspend(struct device *dev)
|
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,
|
.pm = &cros_ec_i2c_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = cros_ec_i2c_probe,
|
.probe = cros_ec_i2c_probe,
|
||||||
|
.remove = cros_ec_i2c_remove,
|
||||||
.id_table = cros_ec_i2c_id,
|
.id_table = cros_ec_i2c_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,11 +8,10 @@
|
|||||||
// (ISH-TP).
|
// (ISH-TP).
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#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/module.h>
|
||||||
#include <linux/pci.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>
|
#include <linux/intel-ish-client-if.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <linux/suspend.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)
|
static int cros_ec_lpc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct cros_ec_device *ec_dev = platform_get_drvdata(pdev);
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
|
|
||||||
adev = ACPI_COMPANION(&pdev->dev);
|
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,
|
acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
|
||||||
cros_ec_lpc_acpi_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[] = {
|
static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
//
|
//
|
||||||
// Copyright (C) 2015 Google, Inc
|
// Copyright (C) 2015 Google, Inc
|
||||||
|
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/module.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 <linux/slab.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/of.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/platform_device.h>
|
||||||
#include <linux/rpmsg.h>
|
#include <linux/rpmsg.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@ -41,6 +41,7 @@ struct cros_ec_rpmsg {
|
|||||||
struct rpmsg_device *rpdev;
|
struct rpmsg_device *rpdev;
|
||||||
struct completion xfer_ack;
|
struct completion xfer_ack;
|
||||||
struct work_struct host_event_work;
|
struct work_struct host_event_work;
|
||||||
|
struct rpmsg_endpoint *ept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,7 +73,6 @@ static int cros_ec_pkt_xfer_rpmsg(struct cros_ec_device *ec_dev,
|
|||||||
struct cros_ec_command *ec_msg)
|
struct cros_ec_command *ec_msg)
|
||||||
{
|
{
|
||||||
struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
|
struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
|
||||||
struct rpmsg_device *rpdev = ec_rpmsg->rpdev;
|
|
||||||
struct ec_host_response *response;
|
struct ec_host_response *response;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
int len;
|
int len;
|
||||||
@ -85,7 +85,7 @@ static int cros_ec_pkt_xfer_rpmsg(struct cros_ec_device *ec_dev,
|
|||||||
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
|
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
|
||||||
|
|
||||||
reinit_completion(&ec_rpmsg->xfer_ack);
|
reinit_completion(&ec_rpmsg->xfer_ack);
|
||||||
ret = rpmsg_send(rpdev->ept, ec_dev->dout, len);
|
ret = rpmsg_send(ec_rpmsg->ept, ec_dev->dout, len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(ec_dev->dev, "rpmsg send failed\n");
|
dev_err(ec_dev->dev, "rpmsg send failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
@ -196,11 +196,24 @@ static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rpmsg_endpoint *
|
||||||
|
cros_ec_rpmsg_create_ept(struct rpmsg_device *rpdev)
|
||||||
|
{
|
||||||
|
struct rpmsg_channel_info chinfo = {};
|
||||||
|
|
||||||
|
strscpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
|
||||||
|
chinfo.src = rpdev->src;
|
||||||
|
chinfo.dst = RPMSG_ADDR_ANY;
|
||||||
|
|
||||||
|
return rpmsg_create_ept(rpdev, cros_ec_rpmsg_callback, NULL, chinfo);
|
||||||
|
}
|
||||||
|
|
||||||
static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev)
|
static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &rpdev->dev;
|
struct device *dev = &rpdev->dev;
|
||||||
struct cros_ec_rpmsg *ec_rpmsg;
|
struct cros_ec_rpmsg *ec_rpmsg;
|
||||||
struct cros_ec_device *ec_dev;
|
struct cros_ec_device *ec_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
|
ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
|
||||||
if (!ec_dev)
|
if (!ec_dev)
|
||||||
@ -225,7 +238,18 @@ static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev)
|
|||||||
INIT_WORK(&ec_rpmsg->host_event_work,
|
INIT_WORK(&ec_rpmsg->host_event_work,
|
||||||
cros_ec_rpmsg_host_event_function);
|
cros_ec_rpmsg_host_event_function);
|
||||||
|
|
||||||
return cros_ec_register(ec_dev);
|
ec_rpmsg->ept = cros_ec_rpmsg_create_ept(rpdev);
|
||||||
|
if (!ec_rpmsg->ept)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = cros_ec_register(ec_dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
rpmsg_destroy_ept(ec_rpmsg->ept);
|
||||||
|
cancel_work_sync(&ec_rpmsg->host_event_work);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cros_ec_rpmsg_remove(struct rpmsg_device *rpdev)
|
static void cros_ec_rpmsg_remove(struct rpmsg_device *rpdev)
|
||||||
@ -233,9 +257,30 @@ static void cros_ec_rpmsg_remove(struct rpmsg_device *rpdev)
|
|||||||
struct cros_ec_device *ec_dev = dev_get_drvdata(&rpdev->dev);
|
struct cros_ec_device *ec_dev = dev_get_drvdata(&rpdev->dev);
|
||||||
struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
|
struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
|
||||||
|
|
||||||
|
cros_ec_unregister(ec_dev);
|
||||||
|
rpmsg_destroy_ept(ec_rpmsg->ept);
|
||||||
cancel_work_sync(&ec_rpmsg->host_event_work);
|
cancel_work_sync(&ec_rpmsg->host_event_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int cros_ec_rpmsg_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return cros_ec_suspend(ec_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cros_ec_rpmsg_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return cros_ec_resume(ec_dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(cros_ec_rpmsg_pm_ops, cros_ec_rpmsg_suspend,
|
||||||
|
cros_ec_rpmsg_resume);
|
||||||
|
|
||||||
static const struct of_device_id cros_ec_rpmsg_of_match[] = {
|
static const struct of_device_id cros_ec_rpmsg_of_match[] = {
|
||||||
{ .compatible = "google,cros-ec-rpmsg", },
|
{ .compatible = "google,cros-ec-rpmsg", },
|
||||||
{ }
|
{ }
|
||||||
@ -246,10 +291,10 @@ static struct rpmsg_driver cros_ec_driver_rpmsg = {
|
|||||||
.drv = {
|
.drv = {
|
||||||
.name = "cros-ec-rpmsg",
|
.name = "cros-ec-rpmsg",
|
||||||
.of_match_table = cros_ec_rpmsg_of_match,
|
.of_match_table = cros_ec_rpmsg_of_match,
|
||||||
|
.pm = &cros_ec_rpmsg_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = cros_ec_rpmsg_probe,
|
.probe = cros_ec_rpmsg_probe,
|
||||||
.remove = cros_ec_rpmsg_remove,
|
.remove = cros_ec_rpmsg_remove,
|
||||||
.callback = cros_ec_rpmsg_callback,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module_rpmsg_driver(cros_ec_driver_rpmsg);
|
module_rpmsg_driver(cros_ec_driver_rpmsg);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/of.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/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
@ -785,6 +785,13 @@ static int cros_ec_spi_probe(struct spi_device *spi)
|
|||||||
return 0;
|
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
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int cros_ec_spi_suspend(struct device *dev)
|
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,
|
.pm = &cros_ec_spi_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = cros_ec_spi_probe,
|
.probe = cros_ec_spi_probe,
|
||||||
|
.remove = cros_ec_spi_remove,
|
||||||
.id_table = cros_ec_spi_id,
|
.id_table = cros_ec_spi_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#define TRACE_SYMBOL(a) {a, #a}
|
#define TRACE_SYMBOL(a) {a, #a}
|
||||||
|
|
||||||
// Generate the list using the following script:
|
// 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 \
|
#define EC_CMDS \
|
||||||
TRACE_SYMBOL(EC_CMD_PROTO_VERSION), \
|
TRACE_SYMBOL(EC_CMD_PROTO_VERSION), \
|
||||||
TRACE_SYMBOL(EC_CMD_HELLO), \
|
TRACE_SYMBOL(EC_CMD_HELLO), \
|
||||||
|
@ -11,8 +11,10 @@
|
|||||||
#if !defined(_CROS_EC_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
|
#if !defined(_CROS_EC_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||||
#define _CROS_EC_TRACE_H_
|
#define _CROS_EC_TRACE_H_
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <linux/types.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>
|
#include <linux/tracepoint.h>
|
||||||
|
|
||||||
|
@ -7,8 +7,9 @@
|
|||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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 <linux/slab.h>
|
||||||
|
|
||||||
#define DRV_NAME "cros-ec-vbc"
|
#define DRV_NAME "cros-ec-vbc"
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ktime.h>
|
#include <linux/ktime.h>
|
||||||
#include <linux/math64.h>
|
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
#include <linux/math64.h>
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
|
|
||||||
@ -209,6 +210,9 @@ static int cros_usbpd_logger_probe(struct platform_device *pd)
|
|||||||
/* Retrieve PD event logs periodically */
|
/* Retrieve PD event logs periodically */
|
||||||
INIT_DELAYED_WORK(&logger->log_work, cros_usbpd_log_check);
|
INIT_DELAYED_WORK(&logger->log_work, cros_usbpd_log_check);
|
||||||
logger->log_workqueue = create_singlethread_workqueue("cros_usbpd_log");
|
logger->log_workqueue = create_singlethread_workqueue("cros_usbpd_log");
|
||||||
|
if (!logger->log_workqueue)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
queue_delayed_work(logger->log_workqueue, &logger->log_work,
|
queue_delayed_work(logger->log_workqueue, &logger->log_work,
|
||||||
CROS_USBPD_LOG_UPDATE_DELAY);
|
CROS_USBPD_LOG_UPDATE_DELAY);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* the OS sends a command to the EC via a write() to a char device,
|
* the OS sends a command to the EC via a write() to a char device,
|
||||||
* and can read the response with a read(). The write() request is
|
* and can read the response with a read(). The write() request is
|
||||||
* verified by the driver to ensure that it is performing only one
|
* verified by the driver to ensure that it is performing only one
|
||||||
* of the whitelisted commands, and that no extraneous data is
|
* of the allowlisted commands, and that no extraneous data is
|
||||||
* being transmitted to the EC. The response is passed directly
|
* being transmitted to the EC. The response is passed directly
|
||||||
* back to the reader with no modification.
|
* back to the reader with no modification.
|
||||||
*
|
*
|
||||||
@ -59,21 +59,10 @@ static DEFINE_IDA(telem_ida);
|
|||||||
#define WILCO_EC_TELEM_GET_TEMP_INFO 0x95
|
#define WILCO_EC_TELEM_GET_TEMP_INFO 0x95
|
||||||
#define WILCO_EC_TELEM_GET_TEMP_READ 0x2C
|
#define WILCO_EC_TELEM_GET_TEMP_READ 0x2C
|
||||||
#define WILCO_EC_TELEM_GET_BATT_EXT_INFO 0x07
|
#define WILCO_EC_TELEM_GET_BATT_EXT_INFO 0x07
|
||||||
|
#define WILCO_EC_TELEM_GET_BATT_PPID_INFO 0x8A
|
||||||
|
|
||||||
#define TELEM_ARGS_SIZE_MAX 30
|
#define TELEM_ARGS_SIZE_MAX 30
|
||||||
|
|
||||||
/**
|
|
||||||
* struct wilco_ec_telem_request - Telemetry command and arguments sent to EC.
|
|
||||||
* @command: One of WILCO_EC_TELEM_GET_* command codes.
|
|
||||||
* @reserved: Must be 0.
|
|
||||||
* @args: The first N bytes are one of telem_args_get_* structs, the rest is 0.
|
|
||||||
*/
|
|
||||||
struct wilco_ec_telem_request {
|
|
||||||
u8 command;
|
|
||||||
u8 reserved;
|
|
||||||
u8 args[TELEM_ARGS_SIZE_MAX];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following telem_args_get_* structs are embedded within the |args| field
|
* The following telem_args_get_* structs are embedded within the |args| field
|
||||||
* of wilco_ec_telem_request.
|
* of wilco_ec_telem_request.
|
||||||
@ -122,6 +111,32 @@ struct telem_args_get_batt_ext_info {
|
|||||||
u8 var_args[5];
|
u8 var_args[5];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct telem_args_get_batt_ppid_info {
|
||||||
|
u8 always1; /* Should always be 1 */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wilco_ec_telem_request - Telemetry command and arguments sent to EC.
|
||||||
|
* @command: One of WILCO_EC_TELEM_GET_* command codes.
|
||||||
|
* @reserved: Must be 0.
|
||||||
|
* @args: The first N bytes are one of telem_args_get_* structs, the rest is 0.
|
||||||
|
*/
|
||||||
|
struct wilco_ec_telem_request {
|
||||||
|
u8 command;
|
||||||
|
u8 reserved;
|
||||||
|
union {
|
||||||
|
u8 buf[TELEM_ARGS_SIZE_MAX];
|
||||||
|
struct telem_args_get_log get_log;
|
||||||
|
struct telem_args_get_version get_version;
|
||||||
|
struct telem_args_get_fan_info get_fan_info;
|
||||||
|
struct telem_args_get_diag_info get_diag_info;
|
||||||
|
struct telem_args_get_temp_info get_temp_info;
|
||||||
|
struct telem_args_get_temp_read get_temp_read;
|
||||||
|
struct telem_args_get_batt_ext_info get_batt_ext_info;
|
||||||
|
struct telem_args_get_batt_ppid_info get_batt_ppid_info;
|
||||||
|
} args;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check_telem_request() - Ensure that a request from userspace is valid.
|
* check_telem_request() - Ensure that a request from userspace is valid.
|
||||||
* @rq: Request buffer copied from userspace.
|
* @rq: Request buffer copied from userspace.
|
||||||
@ -133,7 +148,7 @@ struct telem_args_get_batt_ext_info {
|
|||||||
* We do not want to allow userspace to send arbitrary telemetry commands to
|
* We do not want to allow userspace to send arbitrary telemetry commands to
|
||||||
* the EC. Therefore we check to ensure that
|
* the EC. Therefore we check to ensure that
|
||||||
* 1. The request follows the format of struct wilco_ec_telem_request.
|
* 1. The request follows the format of struct wilco_ec_telem_request.
|
||||||
* 2. The supplied command code is one of the whitelisted commands.
|
* 2. The supplied command code is one of the allowlisted commands.
|
||||||
* 3. The request only contains the necessary data for the header and arguments.
|
* 3. The request only contains the necessary data for the header and arguments.
|
||||||
*/
|
*/
|
||||||
static int check_telem_request(struct wilco_ec_telem_request *rq,
|
static int check_telem_request(struct wilco_ec_telem_request *rq,
|
||||||
@ -146,25 +161,31 @@ static int check_telem_request(struct wilco_ec_telem_request *rq,
|
|||||||
|
|
||||||
switch (rq->command) {
|
switch (rq->command) {
|
||||||
case WILCO_EC_TELEM_GET_LOG:
|
case WILCO_EC_TELEM_GET_LOG:
|
||||||
max_size += sizeof(struct telem_args_get_log);
|
max_size += sizeof(rq->args.get_log);
|
||||||
break;
|
break;
|
||||||
case WILCO_EC_TELEM_GET_VERSION:
|
case WILCO_EC_TELEM_GET_VERSION:
|
||||||
max_size += sizeof(struct telem_args_get_version);
|
max_size += sizeof(rq->args.get_version);
|
||||||
break;
|
break;
|
||||||
case WILCO_EC_TELEM_GET_FAN_INFO:
|
case WILCO_EC_TELEM_GET_FAN_INFO:
|
||||||
max_size += sizeof(struct telem_args_get_fan_info);
|
max_size += sizeof(rq->args.get_fan_info);
|
||||||
break;
|
break;
|
||||||
case WILCO_EC_TELEM_GET_DIAG_INFO:
|
case WILCO_EC_TELEM_GET_DIAG_INFO:
|
||||||
max_size += sizeof(struct telem_args_get_diag_info);
|
max_size += sizeof(rq->args.get_diag_info);
|
||||||
break;
|
break;
|
||||||
case WILCO_EC_TELEM_GET_TEMP_INFO:
|
case WILCO_EC_TELEM_GET_TEMP_INFO:
|
||||||
max_size += sizeof(struct telem_args_get_temp_info);
|
max_size += sizeof(rq->args.get_temp_info);
|
||||||
break;
|
break;
|
||||||
case WILCO_EC_TELEM_GET_TEMP_READ:
|
case WILCO_EC_TELEM_GET_TEMP_READ:
|
||||||
max_size += sizeof(struct telem_args_get_temp_read);
|
max_size += sizeof(rq->args.get_temp_read);
|
||||||
break;
|
break;
|
||||||
case WILCO_EC_TELEM_GET_BATT_EXT_INFO:
|
case WILCO_EC_TELEM_GET_BATT_EXT_INFO:
|
||||||
max_size += sizeof(struct telem_args_get_batt_ext_info);
|
max_size += sizeof(rq->args.get_batt_ext_info);
|
||||||
|
break;
|
||||||
|
case WILCO_EC_TELEM_GET_BATT_PPID_INFO:
|
||||||
|
if (rq->args.get_batt_ppid_info.always1 != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
max_size += sizeof(rq->args.get_batt_ppid_info);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -250,6 +271,7 @@ static ssize_t telem_write(struct file *filp, const char __user *buf,
|
|||||||
|
|
||||||
if (count > sizeof(sess_data->request))
|
if (count > sizeof(sess_data->request))
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
memset(&sess_data->request, 0, sizeof(sess_data->request));
|
||||||
if (copy_from_user(&sess_data->request, buf, count))
|
if (copy_from_user(&sess_data->request, buf, count))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ret = check_telem_request(&sess_data->request, count);
|
ret = check_telem_request(&sess_data->request, count);
|
||||||
|
@ -670,7 +670,7 @@ config CHARGER_RT9455
|
|||||||
|
|
||||||
config CHARGER_CROS_USBPD
|
config CHARGER_CROS_USBPD
|
||||||
tristate "ChromeOS EC based USBPD charger"
|
tristate "ChromeOS EC based USBPD charger"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Say Y here to enable ChromeOS EC based USBPD charger
|
Say Y here to enable ChromeOS EC based USBPD charger
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
* Copyright (c) 2014 - 2018 Google, Inc
|
* Copyright (c) 2014 - 2018 Google, Inc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/mfd/cros_ec.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/platform_device.h>
|
||||||
#include <linux/power_supply.h>
|
#include <linux/power_supply.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -145,7 +145,7 @@ config PWM_CRC
|
|||||||
|
|
||||||
config PWM_CROS_EC
|
config PWM_CROS_EC
|
||||||
tristate "ChromeOS EC PWM driver"
|
tristate "ChromeOS EC PWM driver"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
help
|
help
|
||||||
PWM driver for exposing a PWM attached to the ChromeOS Embedded
|
PWM driver for exposing a PWM attached to the ChromeOS Embedded
|
||||||
Controller.
|
Controller.
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/platform_data/cros_ec_commands.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
#include <linux/platform_data/cros_ec_proto.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pwm.h>
|
#include <linux/pwm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -1274,7 +1274,7 @@ config RTC_DRV_ZYNQMP
|
|||||||
|
|
||||||
config RTC_DRV_CROS_EC
|
config RTC_DRV_CROS_EC
|
||||||
tristate "Chrome OS EC RTC driver"
|
tristate "Chrome OS EC RTC driver"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
help
|
help
|
||||||
If you say yes here you will get support for the
|
If you say yes here you will get support for the
|
||||||
Chrome OS Embedded Controller's RTC.
|
Chrome OS Embedded Controller's RTC.
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/slab.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/arizona/pdata.h
|
||||||
header-test- += linux/mfd/as3711.h
|
header-test- += linux/mfd/as3711.h
|
||||||
header-test- += linux/mfd/as3722.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/da903x.h
|
||||||
header-test- += linux/mfd/da9055/pdata.h
|
header-test- += linux/mfd/da9055/pdata.h
|
||||||
header-test- += linux/mfd/da9063/pdata.h
|
header-test- += linux/mfd/da9063/pdata.h
|
||||||
@ -455,6 +454,7 @@ header-test- += linux/platform_data/ata-pxa.h
|
|||||||
header-test- += linux/platform_data/atmel.h
|
header-test- += linux/platform_data/atmel.h
|
||||||
header-test- += linux/platform_data/bh1770glc.h
|
header-test- += linux/platform_data/bh1770glc.h
|
||||||
header-test- += linux/platform_data/brcmfmac.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/clk-u300.h
|
||||||
header-test- += linux/platform_data/cyttsp4.h
|
header-test- += linux/platform_data/cyttsp4.h
|
||||||
header-test- += linux/platform_data/dma-coh901318.h
|
header-test- += linux/platform_data/dma-coh901318.h
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/irqreturn.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 {
|
enum {
|
||||||
CROS_EC_SENSOR_X,
|
CROS_EC_SENSOR_X,
|
||||||
|
@ -8,183 +8,11 @@
|
|||||||
#ifndef __LINUX_MFD_CROS_EC_H
|
#ifndef __LINUX_MFD_CROS_EC_H
|
||||||
#define __LINUX_MFD_CROS_EC_H
|
#define __LINUX_MFD_CROS_EC_H
|
||||||
|
|
||||||
#include <linux/cdev.h>
|
|
||||||
#include <linux/device.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.
|
* struct cros_ec_dev - ChromeOS EC device entry point.
|
||||||
* @class_dev: Device structure used in sysfs.
|
* @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.
|
* @ec_dev: cros_ec_device structure to talk to the physical device.
|
||||||
* @dev: Pointer to the platform device.
|
* @dev: Pointer to the platform device.
|
||||||
* @debug_info: cros_ec_debugfs structure for debugging information.
|
* @debug_info: cros_ec_debugfs structure for debugging information.
|
||||||
@ -194,7 +22,6 @@ struct cros_ec_debugfs;
|
|||||||
*/
|
*/
|
||||||
struct cros_ec_dev {
|
struct cros_ec_dev {
|
||||||
struct device class_dev;
|
struct device class_dev;
|
||||||
struct cdev cdev;
|
|
||||||
struct cros_ec_device *ec_dev;
|
struct cros_ec_device *ec_dev;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct cros_ec_debugfs *debug_info;
|
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)
|
#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 */
|
#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.
|
* Copyright (C) 2014 Google, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CROS_EC_DEV_H_
|
#ifndef _UAPI_LINUX_CROS_EC_DEV_H_
|
||||||
#define _CROS_EC_DEV_H_
|
#define _UAPI_LINUX_CROS_EC_DEV_H_
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
#include <linux/types.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"
|
#define CROS_EC_DEV_VERSION "1.0.0"
|
||||||
|
|
||||||
@ -31,5 +33,6 @@ struct cros_ec_readmem {
|
|||||||
#define CROS_EC_DEV_IOC 0xEC
|
#define CROS_EC_DEV_IOC 0xEC
|
||||||
#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
|
#define CROS_EC_DEV_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)
|
||||||
|
#define CROS_EC_DEV_IOCEVENTMASK _IO(CROS_EC_DEV_IOC, 2)
|
||||||
|
|
||||||
#endif /* _CROS_EC_DEV_H_ */
|
#endif /* _CROS_EC_DEV_H_ */
|
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_BT_SCO
|
||||||
select SND_SOC_BD28623
|
select SND_SOC_BD28623
|
||||||
select SND_SOC_CQ0093VC
|
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_CS35L32 if I2C
|
||||||
select SND_SOC_CS35L33 if I2C
|
select SND_SOC_CS35L33 if I2C
|
||||||
select SND_SOC_CS35L34 if I2C
|
select SND_SOC_CS35L34 if I2C
|
||||||
@ -477,7 +477,7 @@ config SND_SOC_CQ0093VC
|
|||||||
|
|
||||||
config SND_SOC_CROS_EC_CODEC
|
config SND_SOC_CROS_EC_CODEC
|
||||||
tristate "codec driver for ChromeOS EC"
|
tristate "codec driver for ChromeOS EC"
|
||||||
depends on MFD_CROS_EC
|
depends on CROS_EC
|
||||||
help
|
help
|
||||||
If you say yes here you will get support for the
|
If you say yes here you will get support for the
|
||||||
ChromeOS Embedded Controller's Audio Codec.
|
ChromeOS Embedded Controller's Audio Codec.
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
|
||||||
#include <linux/mfd/cros_ec_commands.h>
|
|
||||||
#include <linux/module.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/platform_device.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
|
@ -99,7 +99,7 @@ config SND_SOC_MSM8996
|
|||||||
|
|
||||||
config SND_SOC_SDM845
|
config SND_SOC_SDM845
|
||||||
tristate "SoC Machine driver for SDM845 boards"
|
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_QDSP6
|
||||||
select SND_SOC_QCOM_COMMON
|
select SND_SOC_QCOM_COMMON
|
||||||
select SND_SOC_RT5663
|
select SND_SOC_RT5663
|
||||||
|
Loading…
Reference in New Issue
Block a user