mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 11:27:47 +00:00
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git
This commit is contained in:
commit
488f681c7a
@ -1,36 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/chrome/google,cros-kbd-led-backlight.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ChromeOS keyboard backlight LED driver.
|
||||
|
||||
maintainers:
|
||||
- Tzung-Bi Shih <tzungbi@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: google,cros-kbd-led-backlight
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cros_ec: ec@0 {
|
||||
compatible = "google,cros-ec-spi";
|
||||
reg = <0>;
|
||||
interrupts = <15 0>;
|
||||
|
||||
kbd-led-backlight {
|
||||
compatible = "google,cros-kbd-led-backlight";
|
||||
};
|
||||
};
|
||||
};
|
@ -108,9 +108,6 @@ properties:
|
||||
pwm:
|
||||
$ref: /schemas/pwm/google,cros-ec-pwm.yaml#
|
||||
|
||||
kbd-led-backlight:
|
||||
$ref: /schemas/chrome/google,cros-kbd-led-backlight.yaml#
|
||||
|
||||
keyboard-controller:
|
||||
$ref: /schemas/input/google,cros-ec-keyb.yaml#
|
||||
|
||||
|
@ -204,6 +204,11 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||
mutex_init(&ec_dev->lock);
|
||||
lockdep_set_class(&ec_dev->lock, &ec_dev->lockdep_key);
|
||||
|
||||
/* Send RWSIG continue to jump to RW for devices using RWSIG. */
|
||||
err = cros_ec_rwsig_continue(ec_dev);
|
||||
if (err)
|
||||
dev_info(dev, "Failed to continue RWSIG: %d\n", err);
|
||||
|
||||
err = cros_ec_query_all(ec_dev);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot identify the EC: error %d\n", err);
|
||||
|
@ -305,7 +305,8 @@ static int cros_ec_i2c_probe(struct i2c_client *client)
|
||||
ec_dev->phys_name = client->adapter->name;
|
||||
ec_dev->din_size = sizeof(struct ec_host_response_i2c) +
|
||||
sizeof(struct ec_response_get_protocol_info);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request_i2c);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request_i2c) +
|
||||
sizeof(struct ec_params_rwsig_action);
|
||||
|
||||
err = cros_ec_register(ec_dev);
|
||||
if (err) {
|
||||
|
@ -557,7 +557,7 @@ static int cros_ec_dev_init(struct ishtp_cl_data *client_data)
|
||||
ec_dev->phys_name = dev_name(dev);
|
||||
ec_dev->din_size = sizeof(struct cros_ish_in_msg) +
|
||||
sizeof(struct ec_response_get_protocol_info);
|
||||
ec_dev->dout_size = sizeof(struct cros_ish_out_msg);
|
||||
ec_dev->dout_size = sizeof(struct cros_ish_out_msg) + sizeof(struct ec_params_rwsig_action);
|
||||
|
||||
return cros_ec_register(ec_dev);
|
||||
}
|
||||
|
@ -70,13 +70,8 @@ struct lpc_driver_data {
|
||||
/**
|
||||
* struct cros_ec_lpc - LPC device-specific data
|
||||
* @mmio_memory_base: The first I/O port addressing EC mapped memory.
|
||||
*/
|
||||
struct cros_ec_lpc {
|
||||
u16 mmio_memory_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct lpc_driver_ops - LPC driver operations
|
||||
* @base: For EC supporting memory mapping, base address of the mapped region.
|
||||
* @mem32: Information about the memory mapped register region, if present.
|
||||
* @read: Copy length bytes from EC address offset into buffer dest.
|
||||
* Returns a negative error code on error, or the 8-bit checksum
|
||||
* of all bytes read.
|
||||
@ -84,18 +79,21 @@ struct cros_ec_lpc {
|
||||
* Returns a negative error code on error, or the 8-bit checksum
|
||||
* of all bytes written.
|
||||
*/
|
||||
struct lpc_driver_ops {
|
||||
int (*read)(unsigned int offset, unsigned int length, u8 *dest);
|
||||
int (*write)(unsigned int offset, unsigned int length, const u8 *msg);
|
||||
struct cros_ec_lpc {
|
||||
u16 mmio_memory_base;
|
||||
void __iomem *base;
|
||||
struct acpi_resource_fixed_memory32 mem32;
|
||||
int (*read)(struct cros_ec_lpc *ec_lpc, unsigned int offset,
|
||||
unsigned int length, u8 *dest);
|
||||
int (*write)(struct cros_ec_lpc *ec_lpc, unsigned int offset,
|
||||
unsigned int length, const u8 *msg);
|
||||
};
|
||||
|
||||
static struct lpc_driver_ops cros_ec_lpc_ops = { };
|
||||
|
||||
/*
|
||||
* A generic instance of the read function of struct lpc_driver_ops, used for
|
||||
* the LPC EC.
|
||||
*/
|
||||
static int cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
|
||||
static int cros_ec_lpc_read_bytes(struct cros_ec_lpc *_, unsigned int offset, unsigned int length,
|
||||
u8 *dest)
|
||||
{
|
||||
u8 sum = 0;
|
||||
@ -114,7 +112,7 @@ static int cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
|
||||
* A generic instance of the write function of struct lpc_driver_ops, used for
|
||||
* the LPC EC.
|
||||
*/
|
||||
static int cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
|
||||
static int cros_ec_lpc_write_bytes(struct cros_ec_lpc *_, unsigned int offset, unsigned int length,
|
||||
const u8 *msg)
|
||||
{
|
||||
u8 sum = 0;
|
||||
@ -133,8 +131,8 @@ static int cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
|
||||
* An instance of the read function of struct lpc_driver_ops, used for the
|
||||
* MEC variant of LPC EC.
|
||||
*/
|
||||
static int cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
|
||||
u8 *dest)
|
||||
static int cros_ec_lpc_mec_read_bytes(struct cros_ec_lpc *ec_lpc, unsigned int offset,
|
||||
unsigned int length, u8 *dest)
|
||||
{
|
||||
int in_range = cros_ec_lpc_mec_in_range(offset, length);
|
||||
|
||||
@ -145,15 +143,15 @@ static int cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
|
||||
cros_ec_lpc_io_bytes_mec(MEC_IO_READ,
|
||||
offset - EC_HOST_CMD_REGION0,
|
||||
length, dest) :
|
||||
cros_ec_lpc_read_bytes(offset, length, dest);
|
||||
cros_ec_lpc_read_bytes(ec_lpc, offset, length, dest);
|
||||
}
|
||||
|
||||
/*
|
||||
* An instance of the write function of struct lpc_driver_ops, used for the
|
||||
* MEC variant of LPC EC.
|
||||
*/
|
||||
static int cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
|
||||
const u8 *msg)
|
||||
static int cros_ec_lpc_mec_write_bytes(struct cros_ec_lpc *ec_lpc, unsigned int offset,
|
||||
unsigned int length, const u8 *msg)
|
||||
{
|
||||
int in_range = cros_ec_lpc_mec_in_range(offset, length);
|
||||
|
||||
@ -164,10 +162,50 @@ static int cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
|
||||
cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE,
|
||||
offset - EC_HOST_CMD_REGION0,
|
||||
length, (u8 *)msg) :
|
||||
cros_ec_lpc_write_bytes(offset, length, msg);
|
||||
cros_ec_lpc_write_bytes(ec_lpc, offset, length, msg);
|
||||
}
|
||||
|
||||
static int ec_response_timed_out(void)
|
||||
static int cros_ec_lpc_direct_read(struct cros_ec_lpc *ec_lpc, unsigned int offset,
|
||||
unsigned int length, u8 *dest)
|
||||
{
|
||||
int sum = 0;
|
||||
int i;
|
||||
|
||||
if (offset < EC_HOST_CMD_REGION0 || offset > EC_LPC_ADDR_MEMMAP +
|
||||
EC_MEMMAP_SIZE) {
|
||||
return cros_ec_lpc_read_bytes(ec_lpc, offset, length, dest);
|
||||
}
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
dest[i] = readb(ec_lpc->base + offset - EC_HOST_CMD_REGION0 + i);
|
||||
sum += dest[i];
|
||||
}
|
||||
|
||||
/* Return checksum of all bytes read */
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int cros_ec_lpc_direct_write(struct cros_ec_lpc *ec_lpc, unsigned int offset,
|
||||
unsigned int length, const u8 *msg)
|
||||
{
|
||||
int sum = 0;
|
||||
int i;
|
||||
|
||||
if (offset < EC_HOST_CMD_REGION0 || offset > EC_LPC_ADDR_MEMMAP +
|
||||
EC_MEMMAP_SIZE) {
|
||||
return cros_ec_lpc_write_bytes(ec_lpc, offset, length, msg);
|
||||
}
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
writeb(msg[i], ec_lpc->base + offset - EC_HOST_CMD_REGION0 + i);
|
||||
sum += msg[i];
|
||||
}
|
||||
|
||||
/* Return checksum of all bytes written */
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int ec_response_timed_out(struct cros_ec_lpc *ec_lpc)
|
||||
{
|
||||
unsigned long one_second = jiffies + HZ;
|
||||
u8 data;
|
||||
@ -175,7 +213,7 @@ static int ec_response_timed_out(void)
|
||||
|
||||
usleep_range(200, 300);
|
||||
do {
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data);
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_CMD, 1, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!(data & EC_LPC_STATUS_BUSY_MASK))
|
||||
@ -189,6 +227,7 @@ static int ec_response_timed_out(void)
|
||||
static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
|
||||
struct cros_ec_command *msg)
|
||||
{
|
||||
struct cros_ec_lpc *ec_lpc = ec->priv;
|
||||
struct ec_host_response response;
|
||||
u8 sum;
|
||||
int ret = 0;
|
||||
@ -199,17 +238,17 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
|
||||
goto done;
|
||||
|
||||
/* Write buffer */
|
||||
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
|
||||
ret = ec_lpc->write(ec_lpc, EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
/* Here we go */
|
||||
sum = EC_COMMAND_PROTOCOL_3;
|
||||
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
|
||||
ret = ec_lpc->write(ec_lpc, EC_LPC_ADDR_HOST_CMD, 1, &sum);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
ret = ec_response_timed_out();
|
||||
ret = ec_response_timed_out(ec_lpc);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
if (ret) {
|
||||
@ -219,7 +258,7 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
|
||||
}
|
||||
|
||||
/* Check result */
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_DATA, 1, &sum);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
msg->result = ret;
|
||||
@ -229,7 +268,7 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
|
||||
|
||||
/* Read back response */
|
||||
dout = (u8 *)&response;
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_PACKET, sizeof(response),
|
||||
dout);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
@ -246,7 +285,7 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
|
||||
}
|
||||
|
||||
/* Read response and process checksum */
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_PACKET +
|
||||
sizeof(response), response.data_len,
|
||||
msg->data);
|
||||
if (ret < 0)
|
||||
@ -270,6 +309,7 @@ done:
|
||||
static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
|
||||
struct cros_ec_command *msg)
|
||||
{
|
||||
struct cros_ec_lpc *ec_lpc = ec->priv;
|
||||
struct ec_lpc_host_args args;
|
||||
u8 sum;
|
||||
int ret = 0;
|
||||
@ -291,7 +331,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
|
||||
sum = msg->command + args.flags + args.command_version + args.data_size;
|
||||
|
||||
/* Copy data and update checksum */
|
||||
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
|
||||
ret = ec_lpc->write(ec_lpc, EC_LPC_ADDR_HOST_PARAM, msg->outsize,
|
||||
msg->data);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
@ -299,18 +339,18 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
|
||||
|
||||
/* Finalize checksum and write args */
|
||||
args.checksum = sum;
|
||||
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
|
||||
ret = ec_lpc->write(ec_lpc, EC_LPC_ADDR_HOST_ARGS, sizeof(args),
|
||||
(u8 *)&args);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
/* Here we go */
|
||||
sum = msg->command;
|
||||
ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
|
||||
ret = ec_lpc->write(ec_lpc, EC_LPC_ADDR_HOST_CMD, 1, &sum);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
ret = ec_response_timed_out();
|
||||
ret = ec_response_timed_out(ec_lpc);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
if (ret) {
|
||||
@ -320,7 +360,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
|
||||
}
|
||||
|
||||
/* Check result */
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_DATA, 1, &sum);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
msg->result = ret;
|
||||
@ -329,7 +369,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
|
||||
goto done;
|
||||
|
||||
/* Read back args */
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
@ -345,7 +385,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
|
||||
sum = msg->command + args.flags + args.command_version + args.data_size;
|
||||
|
||||
/* Read response and update checksum */
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_HOST_PARAM, args.data_size,
|
||||
msg->data);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
@ -381,7 +421,7 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
|
||||
|
||||
/* fixed length */
|
||||
if (bytes) {
|
||||
ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s);
|
||||
ret = ec_lpc->read(ec_lpc, ec_lpc->mmio_memory_base + offset, bytes, s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return bytes;
|
||||
@ -389,7 +429,7 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
|
||||
|
||||
/* string */
|
||||
for (; i < EC_MEMMAP_SIZE; i++, s++) {
|
||||
ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s);
|
||||
ret = ec_lpc->read(ec_lpc, ec_lpc->mmio_memory_base + i, 1, s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
cnt++;
|
||||
@ -419,7 +459,7 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ec_dev->mkbp_event_supported)
|
||||
if (value == ACPI_NOTIFY_CROS_EC_MKBP && ec_dev->mkbp_event_supported)
|
||||
do {
|
||||
ret = cros_ec_get_next_event(ec_dev, NULL,
|
||||
&ec_has_more_events);
|
||||
@ -453,6 +493,20 @@ static struct acpi_device *cros_ec_lpc_get_device(const char *id)
|
||||
return adev;
|
||||
}
|
||||
|
||||
static acpi_status cros_ec_lpc_resources(struct acpi_resource *res, void *data)
|
||||
{
|
||||
struct cros_ec_lpc *ec_lpc = data;
|
||||
|
||||
switch (res->type) {
|
||||
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
|
||||
ec_lpc->mem32 = res->data.fixed_memory32;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -492,8 +546,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (quirks & CROS_EC_LPC_QUIRK_AML_MUTEX) {
|
||||
const char *name
|
||||
= driver_data->quirk_aml_mutex_name;
|
||||
const char *name = driver_data->quirk_aml_mutex_name;
|
||||
ret = cros_ec_lpc_mec_acpi_mutex(ACPI_COMPANION(dev), name);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get AML mutex '%s'", name);
|
||||
@ -502,30 +555,53 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
dev_info(dev, "got AML mutex '%s'", name);
|
||||
}
|
||||
}
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (adev) {
|
||||
/*
|
||||
* Retrieve the resource information in the CRS register, if available.
|
||||
*/
|
||||
status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
|
||||
cros_ec_lpc_resources, ec_lpc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_err(dev, "failed to get resources\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (ec_lpc->mem32.address_length) {
|
||||
ec_lpc->base = devm_ioremap(dev,
|
||||
ec_lpc->mem32.address,
|
||||
ec_lpc->mem32.address_length);
|
||||
if (!ec_lpc->base)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The Framework Laptop (and possibly other non-ChromeOS devices)
|
||||
* only exposes the eight I/O ports that are required for the Microchip EC.
|
||||
* Requesting a larger reservation will fail.
|
||||
*/
|
||||
if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
|
||||
EC_HOST_CMD_MEC_REGION_SIZE, dev_name(dev))) {
|
||||
dev_err(dev, "couldn't reserve MEC region\n");
|
||||
return -EBUSY;
|
||||
ec_lpc->read = cros_ec_lpc_direct_read;
|
||||
ec_lpc->write = cros_ec_lpc_direct_write;
|
||||
}
|
||||
}
|
||||
if (!ec_lpc->read) {
|
||||
/*
|
||||
* The Framework Laptop (and possibly other non-ChromeOS devices)
|
||||
* only exposes the eight I/O ports that are required for the Microchip EC.
|
||||
* Requesting a larger reservation will fail.
|
||||
*/
|
||||
if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
|
||||
EC_HOST_CMD_MEC_REGION_SIZE, dev_name(dev))) {
|
||||
dev_err(dev, "couldn't reserve MEC region\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
|
||||
EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
|
||||
cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
|
||||
EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
|
||||
|
||||
/*
|
||||
* Read the mapped ID twice, the first one is assuming the
|
||||
* EC is a Microchip Embedded Controller (MEC) variant, if the
|
||||
* protocol fails, fallback to the non MEC variant and try to
|
||||
* read again the ID.
|
||||
*/
|
||||
cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
|
||||
cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
|
||||
ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
|
||||
/*
|
||||
* Read the mapped ID twice, the first one is assuming the
|
||||
* EC is a Microchip Embedded Controller (MEC) variant, if the
|
||||
* protocol fails, fallback to the non MEC variant and try to
|
||||
* read again the ID.
|
||||
*/
|
||||
ec_lpc->read = cros_ec_lpc_mec_read_bytes;
|
||||
ec_lpc->write = cros_ec_lpc_mec_write_bytes;
|
||||
}
|
||||
ret = ec_lpc->read(ec_lpc, EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (buf[0] != 'E' || buf[1] != 'C') {
|
||||
@ -536,9 +612,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Re-assign read/write operations for the non MEC variant */
|
||||
cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
|
||||
cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
|
||||
ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2,
|
||||
ec_lpc->read = cros_ec_lpc_read_bytes;
|
||||
ec_lpc->write = cros_ec_lpc_write_bytes;
|
||||
ret = ec_lpc->read(ec_lpc, ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2,
|
||||
buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -573,7 +649,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
ec_dev->cmd_readmem = cros_ec_lpc_readmem;
|
||||
ec_dev->din_size = sizeof(struct ec_host_response) +
|
||||
sizeof(struct ec_response_get_protocol_info);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action);
|
||||
ec_dev->priv = ec_lpc;
|
||||
|
||||
/*
|
||||
@ -598,7 +674,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
* Connect a notify handler to process MKBP messages if we have a
|
||||
* companion ACPI device.
|
||||
*/
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (adev) {
|
||||
status = acpi_install_notify_handler(adev->handle,
|
||||
ACPI_ALL_NOTIFY,
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "cros_ec_trace.h"
|
||||
|
||||
#define EC_COMMAND_RETRIES 50
|
||||
#define RWSIG_CONTINUE_RETRIES 8
|
||||
#define RWSIG_CONTINUE_MAX_ERRORS_IN_ROW 3
|
||||
|
||||
static const int cros_ec_error_map[] = {
|
||||
[EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
|
||||
@ -288,6 +290,64 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cros_ec_rwsig_continue(struct cros_ec_device *ec_dev)
|
||||
{
|
||||
struct cros_ec_command *msg;
|
||||
struct ec_params_rwsig_action *rwsig_action;
|
||||
int ret = 0;
|
||||
int error_count = 0;
|
||||
|
||||
ec_dev->proto_version = 3;
|
||||
|
||||
msg = kmalloc(sizeof(*msg) + sizeof(*rwsig_action), GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
msg->version = 0;
|
||||
msg->command = EC_CMD_RWSIG_ACTION;
|
||||
msg->insize = 0;
|
||||
msg->outsize = sizeof(*rwsig_action);
|
||||
|
||||
rwsig_action = (struct ec_params_rwsig_action *)msg->data;
|
||||
rwsig_action->action = RWSIG_ACTION_CONTINUE;
|
||||
|
||||
for (int i = 0; i < RWSIG_CONTINUE_RETRIES; i++) {
|
||||
ret = cros_ec_send_command(ec_dev, msg);
|
||||
|
||||
if (ret < 0) {
|
||||
if (++error_count >= RWSIG_CONTINUE_MAX_ERRORS_IN_ROW)
|
||||
break;
|
||||
} else if (msg->result == EC_RES_INVALID_COMMAND) {
|
||||
/*
|
||||
* If EC_RES_INVALID_COMMAND is retured, it means RWSIG
|
||||
* is not supported or EC is already in RW, so there is
|
||||
* nothing left to do.
|
||||
*/
|
||||
break;
|
||||
} else if (msg->result != EC_RES_SUCCESS) {
|
||||
/* Unexpected command error. */
|
||||
ret = cros_ec_map_error(msg->result);
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
* The EC_CMD_RWSIG_ACTION succeed. Send the command
|
||||
* more times, to make sure EC is in RW. A following
|
||||
* command can timeout, because EC may need some time to
|
||||
* initialize after jump to RW.
|
||||
*/
|
||||
error_count = 0;
|
||||
}
|
||||
|
||||
if (ret != -ETIMEDOUT)
|
||||
usleep_range(90000, 100000);
|
||||
}
|
||||
|
||||
kfree(msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_rwsig_continue);
|
||||
|
||||
static int cros_ec_get_proto_info(struct cros_ec_device *ec_dev, int devidx)
|
||||
{
|
||||
struct cros_ec_command *msg;
|
||||
@ -306,15 +366,6 @@ static int cros_ec_get_proto_info(struct cros_ec_device *ec_dev, int devidx)
|
||||
msg->insize = sizeof(*info);
|
||||
|
||||
ret = cros_ec_send_command(ec_dev, msg);
|
||||
/*
|
||||
* Send command once again when timeout occurred.
|
||||
* Fingerprint MCU (FPMCU) is restarted during system boot which
|
||||
* introduces small window in which FPMCU won't respond for any
|
||||
* messages sent by kernel. There is no need to wait before next
|
||||
* attempt because we waited at least EC_MSG_DEADLINE_MS.
|
||||
*/
|
||||
if (ret == -ETIMEDOUT)
|
||||
ret = cros_ec_send_command(ec_dev, msg);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_dbg(ec_dev->dev,
|
||||
|
@ -231,7 +231,7 @@ static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||
ec_dev->phys_name = dev_name(&rpdev->dev);
|
||||
ec_dev->din_size = sizeof(struct ec_host_response) +
|
||||
sizeof(struct ec_response_get_protocol_info);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action);
|
||||
dev_set_drvdata(dev, ec_dev);
|
||||
|
||||
ec_rpmsg->rpdev = rpdev;
|
||||
|
@ -766,7 +766,7 @@ static int cros_ec_spi_probe(struct spi_device *spi)
|
||||
ec_dev->din_size = EC_MSG_PREAMBLE_COUNT +
|
||||
sizeof(struct ec_host_response) +
|
||||
sizeof(struct ec_response_get_protocol_info);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action);
|
||||
|
||||
ec_spi->last_transfer_ns = ktime_get_ns();
|
||||
|
||||
|
@ -122,8 +122,10 @@
|
||||
TRACE_SYMBOL(EC_CMD_ENTERING_MODE), \
|
||||
TRACE_SYMBOL(EC_CMD_I2C_PASSTHRU_PROTECT), \
|
||||
TRACE_SYMBOL(EC_CMD_CEC_WRITE_MSG), \
|
||||
TRACE_SYMBOL(EC_CMD_CEC_READ_MSG), \
|
||||
TRACE_SYMBOL(EC_CMD_CEC_SET), \
|
||||
TRACE_SYMBOL(EC_CMD_CEC_GET), \
|
||||
TRACE_SYMBOL(EC_CMD_CEC_PORT_COUNT), \
|
||||
TRACE_SYMBOL(EC_CMD_EC_CODEC), \
|
||||
TRACE_SYMBOL(EC_CMD_EC_CODEC_DMIC), \
|
||||
TRACE_SYMBOL(EC_CMD_EC_CODEC_I2S_RX), \
|
||||
@ -161,11 +163,18 @@
|
||||
TRACE_SYMBOL(EC_CMD_ADC_READ), \
|
||||
TRACE_SYMBOL(EC_CMD_ROLLBACK_INFO), \
|
||||
TRACE_SYMBOL(EC_CMD_AP_RESET), \
|
||||
TRACE_SYMBOL(EC_CMD_PCHG_COUNT), \
|
||||
TRACE_SYMBOL(EC_CMD_PCHG), \
|
||||
TRACE_SYMBOL(EC_CMD_PCHG_UPDATE), \
|
||||
TRACE_SYMBOL(EC_CMD_REGULATOR_GET_INFO), \
|
||||
TRACE_SYMBOL(EC_CMD_REGULATOR_ENABLE), \
|
||||
TRACE_SYMBOL(EC_CMD_REGULATOR_IS_ENABLED), \
|
||||
TRACE_SYMBOL(EC_CMD_REGULATOR_SET_VOLTAGE), \
|
||||
TRACE_SYMBOL(EC_CMD_REGULATOR_GET_VOLTAGE), \
|
||||
TRACE_SYMBOL(EC_CMD_TYPEC_DISCOVERY), \
|
||||
TRACE_SYMBOL(EC_CMD_TYPEC_CONTROL), \
|
||||
TRACE_SYMBOL(EC_CMD_TYPEC_STATUS), \
|
||||
TRACE_SYMBOL(EC_CMD_TYPEC_VDM_RESPONSE), \
|
||||
TRACE_SYMBOL(EC_CMD_CR51_BASE), \
|
||||
TRACE_SYMBOL(EC_CMD_CR51_LAST), \
|
||||
TRACE_SYMBOL(EC_CMD_FP_PASSTHRU), \
|
||||
@ -184,6 +193,7 @@
|
||||
TRACE_SYMBOL(EC_CMD_BATTERY_GET_STATIC), \
|
||||
TRACE_SYMBOL(EC_CMD_BATTERY_GET_DYNAMIC), \
|
||||
TRACE_SYMBOL(EC_CMD_CHARGER_CONTROL), \
|
||||
TRACE_SYMBOL(EC_CMD_USB_PD_MUX_ACK), \
|
||||
TRACE_SYMBOL(EC_CMD_BOARD_SPECIFIC_BASE), \
|
||||
TRACE_SYMBOL(EC_CMD_BOARD_SPECIFIC_LAST)
|
||||
|
||||
|
@ -283,7 +283,7 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
|
||||
ec_dev->pkt_xfer = cros_ec_uart_pkt_xfer;
|
||||
ec_dev->din_size = sizeof(struct ec_host_response) +
|
||||
sizeof(struct ec_response_get_protocol_info);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request);
|
||||
ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action);
|
||||
|
||||
serdev_device_set_client_ops(serdev, &cros_ec_uart_client_ops);
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#define DRV_NAME "cros-ec-vbc"
|
||||
|
||||
static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *att, char *buf,
|
||||
const struct bin_attribute *att, char *buf,
|
||||
loff_t pos, size_t count)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
@ -59,7 +59,7 @@ static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
|
||||
}
|
||||
|
||||
static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
const struct bin_attribute *attr, char *buf,
|
||||
loff_t pos, size_t count)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
@ -99,16 +99,16 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
|
||||
return data_sz;
|
||||
}
|
||||
|
||||
static BIN_ATTR_RW(vboot_context, 16);
|
||||
static const BIN_ATTR_RW(vboot_context, 16);
|
||||
|
||||
static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
|
||||
static const struct bin_attribute *const cros_ec_vbc_bin_attrs[] = {
|
||||
&bin_attr_vboot_context,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group cros_ec_vbc_attr_group = {
|
||||
.name = "vbc",
|
||||
.bin_attrs = cros_ec_vbc_bin_attrs,
|
||||
.bin_attrs_new = cros_ec_vbc_bin_attrs,
|
||||
};
|
||||
|
||||
static int cros_ec_vbc_probe(struct platform_device *pd)
|
||||
|
@ -121,7 +121,17 @@ static const struct keyboard_led_drvdata keyboard_led_drvdata_acpi = {
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#if IS_ENABLED(CONFIG_CROS_EC)
|
||||
#if IS_ENABLED(CONFIG_MFD_CROS_EC_DEV)
|
||||
static int keyboard_led_init_ec_pwm_mfd(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct cros_ec_device *cros_ec = ec_dev->ec_dev;
|
||||
struct keyboard_led *keyboard_led = platform_get_drvdata(pdev);
|
||||
|
||||
keyboard_led->ec = cros_ec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
keyboard_led_set_brightness_ec_pwm(struct led_classdev *cdev,
|
||||
@ -169,44 +179,6 @@ keyboard_led_get_brightness_ec_pwm(struct led_classdev *cdev)
|
||||
return resp->percent;
|
||||
}
|
||||
|
||||
static int keyboard_led_init_ec_pwm(struct platform_device *pdev)
|
||||
{
|
||||
struct keyboard_led *keyboard_led = platform_get_drvdata(pdev);
|
||||
|
||||
keyboard_led->ec = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!keyboard_led->ec) {
|
||||
dev_err(&pdev->dev, "no parent EC device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const __maybe_unused struct keyboard_led_drvdata keyboard_led_drvdata_ec_pwm = {
|
||||
.init = keyboard_led_init_ec_pwm,
|
||||
.brightness_set_blocking = keyboard_led_set_brightness_ec_pwm,
|
||||
.brightness_get = keyboard_led_get_brightness_ec_pwm,
|
||||
.max_brightness = KEYBOARD_BACKLIGHT_MAX,
|
||||
};
|
||||
|
||||
#else /* IS_ENABLED(CONFIG_CROS_EC) */
|
||||
|
||||
static const __maybe_unused struct keyboard_led_drvdata keyboard_led_drvdata_ec_pwm = {};
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_CROS_EC) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_MFD_CROS_EC_DEV)
|
||||
static int keyboard_led_init_ec_pwm_mfd(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct cros_ec_device *cros_ec = ec_dev->ec_dev;
|
||||
struct keyboard_led *keyboard_led = platform_get_drvdata(pdev);
|
||||
|
||||
keyboard_led->ec = cros_ec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct keyboard_led_drvdata keyboard_led_drvdata_ec_pwm_mfd = {
|
||||
.init = keyboard_led_init_ec_pwm_mfd,
|
||||
.brightness_set_blocking = keyboard_led_set_brightness_ec_pwm,
|
||||
@ -229,7 +201,7 @@ static int keyboard_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct keyboard_led_drvdata *drvdata;
|
||||
struct keyboard_led *keyboard_led;
|
||||
int error;
|
||||
int err;
|
||||
|
||||
if (keyboard_led_is_mfd_device(pdev))
|
||||
drvdata = &keyboard_led_drvdata_ec_pwm_mfd;
|
||||
@ -244,9 +216,9 @@ static int keyboard_led_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, keyboard_led);
|
||||
|
||||
if (drvdata->init) {
|
||||
error = drvdata->init(pdev);
|
||||
if (error)
|
||||
return error;
|
||||
err = drvdata->init(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
keyboard_led->cdev.name = "chromeos::kbd_backlight";
|
||||
@ -256,13 +228,10 @@ static int keyboard_led_probe(struct platform_device *pdev)
|
||||
keyboard_led->cdev.brightness_set_blocking = drvdata->brightness_set_blocking;
|
||||
keyboard_led->cdev.brightness_get = drvdata->brightness_get;
|
||||
|
||||
error = devm_led_classdev_register(&pdev->dev, &keyboard_led->cdev);
|
||||
if (error == -EEXIST) /* Already bound via other mechanism */
|
||||
err = devm_led_classdev_register(&pdev->dev, &keyboard_led->cdev);
|
||||
if (err == -EEXIST) /* Already bound via other mechanism */
|
||||
return -ENODEV;
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
@ -273,17 +242,6 @@ static const struct acpi_device_id keyboard_led_acpi_match[] = {
|
||||
MODULE_DEVICE_TABLE(acpi, keyboard_led_acpi_match);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id keyboard_led_of_match[] = {
|
||||
{
|
||||
.compatible = "google,cros-kbd-led-backlight",
|
||||
.data = &keyboard_led_drvdata_ec_pwm,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, keyboard_led_of_match);
|
||||
#endif
|
||||
|
||||
static const struct platform_device_id keyboard_led_id[] = {
|
||||
{ "cros-keyboard-leds", 0 },
|
||||
{}
|
||||
@ -294,7 +252,6 @@ static struct platform_driver keyboard_led_driver = {
|
||||
.driver = {
|
||||
.name = "cros-keyboard-leds",
|
||||
.acpi_match_table = ACPI_PTR(keyboard_led_acpi_match),
|
||||
.of_match_table = of_match_ptr(keyboard_led_of_match),
|
||||
},
|
||||
.probe = keyboard_led_probe,
|
||||
.id_table = keyboard_led_id,
|
||||
|
@ -41,6 +41,11 @@
|
||||
#define EC_MAX_REQUEST_OVERHEAD 1
|
||||
#define EC_MAX_RESPONSE_OVERHEAD 32
|
||||
|
||||
/*
|
||||
* ACPI notify value for MKBP host event.
|
||||
*/
|
||||
#define ACPI_NOTIFY_CROS_EC_MKBP 0x80
|
||||
|
||||
/*
|
||||
* EC panic is not covered by the standard (0-F) ACPI notify values.
|
||||
* Arbitrarily choosing B0 to notify ec panic, which is in the 84-BF
|
||||
@ -246,6 +251,8 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
|
||||
int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
int cros_ec_rwsig_continue(struct cros_ec_device *ec_dev);
|
||||
|
||||
int cros_ec_query_all(struct cros_ec_device *ec_dev);
|
||||
|
||||
int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
|
||||
|
Loading…
x
Reference in New Issue
Block a user