diff --git a/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml b/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml deleted file mode 100644 index c94ab8f9e0b8..000000000000 --- a/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml +++ /dev/null @@ -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 - -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"; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml index aac8819bd00b..50f457090066 100644 --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml @@ -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# diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index e821b3d39590..110771a8645e 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -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); diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c index 62662ba5bf6e..38af97cdaab2 100644 --- a/drivers/platform/chrome/cros_ec_i2c.c +++ b/drivers/platform/chrome/cros_ec_i2c.c @@ -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) { diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index 5ac37bd024c8..7e7190b30cbb 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -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); } diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 8470b7f2b135..5a2f1d98b350 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -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 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec, 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,49 @@ 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_SUCCESS(status) && 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 +608,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 +645,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 +670,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, diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 5c9a53dffcf9..877b107fee4b 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -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 @@ static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev, uint3 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, diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index 39d3b50a7c09..bc2666491db1 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -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; diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 08f566cc1480..8ca0f854e7ac 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -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(); diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c index 425e9441b7ca..9827b3117597 100644 --- a/drivers/platform/chrome/cros_ec_trace.c +++ b/drivers/platform/chrome/cros_ec_trace.c @@ -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) diff --git a/drivers/platform/chrome/cros_ec_uart.c b/drivers/platform/chrome/cros_ec_uart.c index 62bc24f6dcc7..19c179d49c90 100644 --- a/drivers/platform/chrome/cros_ec_uart.c +++ b/drivers/platform/chrome/cros_ec_uart.c @@ -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); diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c index 7bdb489354c5..963c4db23055 100644 --- a/drivers/platform/chrome/cros_ec_vbc.c +++ b/drivers/platform/chrome/cros_ec_vbc.c @@ -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) diff --git a/drivers/platform/chrome/cros_kbd_led_backlight.c b/drivers/platform/chrome/cros_kbd_led_backlight.c index 78097c8a4966..fc27bd7fc4b9 100644 --- a/drivers/platform/chrome/cros_kbd_led_backlight.c +++ b/drivers/platform/chrome/cros_kbd_led_backlight.c @@ -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, diff --git a/drivers/platform/chrome/cros_usbpd_logger.c b/drivers/platform/chrome/cros_usbpd_logger.c index cd71f1caea81..7ce75e2e039e 100644 --- a/drivers/platform/chrome/cros_usbpd_logger.c +++ b/drivers/platform/chrome/cros_usbpd_logger.c @@ -13,6 +13,7 @@ #include #include #include +#include #define DRV_NAME "cros-usbpd-logger" @@ -135,8 +136,8 @@ static void cros_usbpd_print_log_entry(struct ec_response_pd_log *r, len += append_str(buf, len, "Power supply fault: %s", fault); break; case PD_EVENT_VIDEO_DP_MODE: - len += append_str(buf, len, "DP mode %sabled", r->data == 1 ? - "en" : "dis"); + len += append_str(buf, len, "DP mode %s", + str_enabled_disabled(r->data == 1)); break; case PD_EVENT_VIDEO_CODEC: minfo = (struct mcdp_info *)r->payload; diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index b34ed0cc1f8d..3ec24f445c29 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -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,