diff options
Diffstat (limited to 'drivers/platform')
27 files changed, 437 insertions, 165 deletions
diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 47d19f7e295a..e821b3d39590 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -388,8 +388,8 @@ EXPORT_SYMBOL(cros_ec_suspend_late); */ int cros_ec_suspend(struct cros_ec_device *ec_dev) { - cros_ec_send_suspend_event(ec_dev); - cros_ec_disable_irq(ec_dev); + cros_ec_suspend_prepare(ec_dev); + cros_ec_suspend_late(ec_dev); return 0; } EXPORT_SYMBOL(cros_ec_suspend); diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index e1d313246beb..4525ad1b59f4 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -26,6 +26,10 @@ #define CIRC_ADD(idx, size, value) (((idx) + (value)) & ((size) - 1)) +static unsigned int log_poll_period_ms = LOG_POLL_SEC * MSEC_PER_SEC; +module_param(log_poll_period_ms, uint, 0644); +MODULE_PARM_DESC(log_poll_period_ms, "EC log polling period(ms)"); + /* waitqueue for log readers */ static DECLARE_WAIT_QUEUE_HEAD(cros_ec_debugfs_log_wq); @@ -57,7 +61,7 @@ struct cros_ec_debugfs { /* * We need to make sure that the EC log buffer on the UART is large enough, - * so that it is unlikely enough to overlow within LOG_POLL_SEC. + * so that it is unlikely enough to overlow within log_poll_period_ms. */ static void cros_ec_console_log_work(struct work_struct *__work) { @@ -119,7 +123,7 @@ static void cros_ec_console_log_work(struct work_struct *__work) resched: schedule_delayed_work(&debug_info->log_poll_work, - msecs_to_jiffies(LOG_POLL_SEC * 1000)); + msecs_to_jiffies(log_poll_period_ms)); } static int cros_ec_console_log_open(struct inode *inode, struct file *file) @@ -330,6 +334,7 @@ static int ec_read_version_supported(struct cros_ec_dev *ec) if (!msg) return 0; + msg->version = 1; msg->command = EC_CMD_GET_CMD_VERSIONS + ec->cmd_offset; msg->outsize = sizeof(*params); msg->insize = sizeof(*response); diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index ddfbfec44f4c..f0470248b109 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -39,6 +39,16 @@ static bool cros_ec_lpc_acpi_device_found; * be used as the base port for EC mapped memory. */ #define CROS_EC_LPC_QUIRK_REMAP_MEMORY BIT(0) +/* + * Indicates that lpc_driver_data.quirk_acpi_id should be used to find + * the ACPI device. + */ +#define CROS_EC_LPC_QUIRK_ACPI_ID BIT(1) +/* + * Indicates that lpc_driver_data.quirk_aml_mutex_name should be used + * to find an AML mutex to protect access to Microchip EC. + */ +#define CROS_EC_LPC_QUIRK_AML_MUTEX BIT(2) /** * struct lpc_driver_data - driver data attached to a DMI device ID to indicate @@ -46,10 +56,15 @@ static bool cros_ec_lpc_acpi_device_found; * @quirks: a bitfield composed of quirks from CROS_EC_LPC_QUIRK_* * @quirk_mmio_memory_base: The first I/O port addressing EC mapped memory (used * when quirk ...REMAP_MEMORY is set.) + * @quirk_acpi_id: An ACPI HID to be used to find the ACPI device. + * @quirk_aml_mutex_name: The name of an AML mutex to be used to protect access + * to Microchip EC. */ struct lpc_driver_data { u32 quirks; u16 quirk_mmio_memory_base; + const char *quirk_acpi_id; + const char *quirk_aml_mutex_name; }; /** @@ -62,14 +77,16 @@ struct cros_ec_lpc { /** * struct lpc_driver_ops - LPC driver operations - * @read: Copy length bytes from EC address offset into buffer dest. Returns - * the 8-bit checksum of all bytes read. - * @write: Copy length bytes from buffer msg into EC address offset. Returns - * the 8-bit checksum of all bytes written. + * @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. + * @write: Copy length bytes from buffer msg into EC address offset. + * Returns a negative error code on error, or the 8-bit checksum + * of all bytes written. */ struct lpc_driver_ops { - u8 (*read)(unsigned int offset, unsigned int length, u8 *dest); - u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg); + int (*read)(unsigned int offset, unsigned int length, u8 *dest); + int (*write)(unsigned int offset, unsigned int length, const u8 *msg); }; static struct lpc_driver_ops cros_ec_lpc_ops = { }; @@ -78,10 +95,10 @@ 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 u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, - u8 *dest) +static int cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, + u8 *dest) { - int sum = 0; + u8 sum = 0; int i; for (i = 0; i < length; ++i) { @@ -97,10 +114,10 @@ static u8 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 u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, - const u8 *msg) +static int cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, + const u8 *msg) { - int sum = 0; + u8 sum = 0; int i; for (i = 0; i < length; ++i) { @@ -116,13 +133,13 @@ static u8 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 u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length, - u8 *dest) +static int cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length, + u8 *dest) { int in_range = cros_ec_lpc_mec_in_range(offset, length); if (in_range < 0) - return 0; + return in_range; return in_range ? cros_ec_lpc_io_bytes_mec(MEC_IO_READ, @@ -135,13 +152,13 @@ static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length, * An instance of the write function of struct lpc_driver_ops, used for the * MEC variant of LPC EC. */ -static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length, - const u8 *msg) +static int cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length, + const u8 *msg) { int in_range = cros_ec_lpc_mec_in_range(offset, length); if (in_range < 0) - return 0; + return in_range; return in_range ? cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, @@ -154,11 +171,14 @@ static int ec_response_timed_out(void) { unsigned long one_second = jiffies + HZ; u8 data; + int ret; usleep_range(200, 300); do { - if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) & - EC_LPC_STATUS_BUSY_MASK)) + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data); + if (ret < 0) + return ret; + if (!(data & EC_LPC_STATUS_BUSY_MASK)) return 0; usleep_range(100, 200); } while (time_before(jiffies, one_second)); @@ -179,28 +199,41 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec, goto done; /* Write buffer */ - cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout); + ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout); + if (ret < 0) + goto done; /* Here we go */ sum = EC_COMMAND_PROTOCOL_3; - cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum); + ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum); + if (ret < 0) + goto done; - if (ec_response_timed_out()) { + ret = ec_response_timed_out(); + if (ret < 0) + goto done; + if (ret) { dev_warn(ec->dev, "EC response timed out\n"); ret = -EIO; goto done; } /* Check result */ - msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum); + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum); + if (ret < 0) + goto done; + msg->result = ret; ret = cros_ec_check_result(ec, msg); if (ret) goto done; /* Read back response */ dout = (u8 *)&response; - sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response), + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response), dout); + if (ret < 0) + goto done; + sum = ret; msg->result = response.result; @@ -213,9 +246,12 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec, } /* Read response and process checksum */ - sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET + - sizeof(response), response.data_len, - msg->data); + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET + + sizeof(response), response.data_len, + msg->data); + if (ret < 0) + goto done; + sum += ret; if (sum) { dev_err(ec->dev, @@ -255,32 +291,47 @@ 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 */ - sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize, - msg->data); + ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize, + msg->data); + if (ret < 0) + goto done; + sum += ret; /* Finalize checksum and write args */ args.checksum = sum; - cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args), - (u8 *)&args); + ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args), + (u8 *)&args); + if (ret < 0) + goto done; /* Here we go */ sum = msg->command; - cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum); + ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum); + if (ret < 0) + goto done; - if (ec_response_timed_out()) { + ret = ec_response_timed_out(); + if (ret < 0) + goto done; + if (ret) { dev_warn(ec->dev, "EC response timed out\n"); ret = -EIO; goto done; } /* Check result */ - msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum); + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum); + if (ret < 0) + goto done; + msg->result = ret; ret = cros_ec_check_result(ec, msg); if (ret) goto done; /* Read back args */ - cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args); + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args); + if (ret < 0) + goto done; if (args.data_size > msg->insize) { dev_err(ec->dev, @@ -294,8 +345,11 @@ 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 */ - sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size, - msg->data); + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size, + msg->data); + if (ret < 0) + goto done; + sum += ret; /* Verify checksum */ if (args.checksum != sum) { @@ -320,19 +374,24 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset, int i = offset; char *s = dest; int cnt = 0; + int ret; if (offset >= EC_MEMMAP_SIZE - bytes) return -EINVAL; /* fixed length */ if (bytes) { - cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s); + ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s); + if (ret < 0) + return ret; return bytes; } /* string */ for (; i < EC_MEMMAP_SIZE; i++, s++) { - cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s); + ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s); + if (ret < 0) + return ret; cnt++; if (!*s) break; @@ -374,6 +433,26 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) pm_system_wakeup(); } +static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level, + void *context, void **retval) +{ + *(struct acpi_device **)context = acpi_fetch_acpi_dev(handle); + return AE_CTRL_TERMINATE; +} + +static struct acpi_device *cros_ec_lpc_get_device(const char *id) +{ + struct acpi_device *adev = NULL; + acpi_status status = acpi_get_devices(id, cros_ec_lpc_parse_device, + &adev, NULL); + if (ACPI_FAILURE(status)) { + pr_warn(DRV_NAME ": Looking for %s failed\n", id); + return NULL; + } + + return adev; +} + static int cros_ec_lpc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -401,6 +480,27 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) if (quirks & CROS_EC_LPC_QUIRK_REMAP_MEMORY) ec_lpc->mmio_memory_base = driver_data->quirk_mmio_memory_base; + + if (quirks & CROS_EC_LPC_QUIRK_ACPI_ID) { + adev = cros_ec_lpc_get_device(driver_data->quirk_acpi_id); + if (!adev) { + dev_err(dev, "failed to get ACPI device '%s'", + driver_data->quirk_acpi_id); + return -ENODEV; + } + ACPI_COMPANION_SET(dev, adev); + } + + if (quirks & CROS_EC_LPC_QUIRK_AML_MUTEX) { + 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); + return ret; + } + dev_info(dev, "got AML mutex '%s'", name); + } } /* @@ -425,7 +525,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) */ cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes; cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes; - cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf); + ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf); + if (ret < 0) + return ret; if (buf[0] != 'E' || buf[1] != 'C') { if (!devm_request_region(dev, ec_lpc->mmio_memory_base, EC_MEMMAP_SIZE, dev_name(dev))) { @@ -436,8 +538,10 @@ 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; - cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2, - buf); + ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2, + buf); + if (ret < 0) + return ret; if (buf[0] != 'E' || buf[1] != 'C') { dev_err(dev, "EC ID not detected\n"); return -ENODEV; @@ -532,6 +636,12 @@ static const struct lpc_driver_data framework_laptop_amd_lpc_driver_data __initc .quirk_mmio_memory_base = 0xE00, }; +static const struct lpc_driver_data framework_laptop_11_lpc_driver_data __initconst = { + .quirks = CROS_EC_LPC_QUIRK_ACPI_ID|CROS_EC_LPC_QUIRK_AML_MUTEX, + .quirk_acpi_id = "PNP0C09", + .quirk_aml_mutex_name = "ECMT", +}; + static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = { { /* @@ -600,6 +710,7 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "Framework"), DMI_MATCH(DMI_PRODUCT_NAME, "Laptop"), }, + .driver_data = (void *)&framework_laptop_11_lpc_driver_data, }, { /* sentinel */ } }; @@ -661,23 +772,12 @@ static struct platform_device cros_ec_lpc_device = { .name = DRV_NAME }; -static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level, - void *context, void **retval) -{ - *(bool *)context = true; - return AE_CTRL_TERMINATE; -} - static int __init cros_ec_lpc_init(void) { int ret; - acpi_status status; const struct dmi_system_id *dmi_match; - status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device, - &cros_ec_lpc_acpi_device_found, NULL); - if (ACPI_FAILURE(status)) - pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME); + cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME); dmi_match = dmi_first_match(cros_ec_lpc_dmi_table); diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c b/drivers/platform/chrome/cros_ec_lpc_mec.c index 0d9c79b270ce..a56584171168 100644 --- a/drivers/platform/chrome/cros_ec_lpc_mec.c +++ b/drivers/platform/chrome/cros_ec_lpc_mec.c @@ -10,14 +10,66 @@ #include "cros_ec_lpc_mec.h" +#define ACPI_LOCK_DELAY_MS 500 + /* * This mutex must be held while accessing the EMI unit. We can't rely on the * EC mutex because memmap data may be accessed without it being held. */ static DEFINE_MUTEX(io_mutex); +/* + * An alternative mutex to be used when the ACPI AML code may also + * access memmap data. When set, this mutex is used in preference to + * io_mutex. + */ +static acpi_handle aml_mutex; + static u16 mec_emi_base, mec_emi_end; /** + * cros_ec_lpc_mec_lock() - Acquire mutex for EMI + * + * @return: Negative error code, or zero for success + */ +static int cros_ec_lpc_mec_lock(void) +{ + bool success; + + if (!aml_mutex) { + mutex_lock(&io_mutex); + return 0; + } + + success = ACPI_SUCCESS(acpi_acquire_mutex(aml_mutex, + NULL, ACPI_LOCK_DELAY_MS)); + if (!success) + return -EBUSY; + + return 0; +} + +/** + * cros_ec_lpc_mec_unlock() - Release mutex for EMI + * + * @return: Negative error code, or zero for success + */ +static int cros_ec_lpc_mec_unlock(void) +{ + bool success; + + if (!aml_mutex) { + mutex_unlock(&io_mutex); + return 0; + } + + success = ACPI_SUCCESS(acpi_release_mutex(aml_mutex, NULL)); + if (!success) + return -EBUSY; + + return 0; +} + +/** * cros_ec_lpc_mec_emi_write_address() - Initialize EMI at a given address. * * @addr: Starting read / write address @@ -41,9 +93,6 @@ static void cros_ec_lpc_mec_emi_write_address(u16 addr, */ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length) { - if (length == 0) - return -EINVAL; - if (WARN_ON(mec_emi_base == 0 || mec_emi_end == 0)) return -EINVAL; @@ -67,16 +116,21 @@ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length) * @length: Number of bytes to read / write * @buf: Destination / source buffer * - * Return: 8-bit checksum of all bytes read / written + * @return: A negative error code on error, or 8-bit checksum of all + * bytes read / written */ -u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, - unsigned int offset, unsigned int length, - u8 *buf) +int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, + unsigned int offset, unsigned int length, + u8 *buf) { int i = 0; int io_addr; u8 sum = 0; enum cros_ec_lpc_mec_emi_access_mode access, new_access; + int ret; + + if (length == 0) + return 0; /* Return checksum of 0 if window is not initialized */ WARN_ON(mec_emi_base == 0 || mec_emi_end == 0); @@ -92,7 +146,9 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, else access = ACCESS_TYPE_LONG_AUTO_INCREMENT; - mutex_lock(&io_mutex); + ret = cros_ec_lpc_mec_lock(); + if (ret) + return ret; /* Initialize I/O at desired address */ cros_ec_lpc_mec_emi_write_address(offset, access); @@ -134,7 +190,9 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, } done: - mutex_unlock(&io_mutex); + ret = cros_ec_lpc_mec_unlock(); + if (ret) + return ret; return sum; } @@ -146,3 +204,18 @@ void cros_ec_lpc_mec_init(unsigned int base, unsigned int end) mec_emi_end = end; } EXPORT_SYMBOL(cros_ec_lpc_mec_init); + +int cros_ec_lpc_mec_acpi_mutex(struct acpi_device *adev, const char *pathname) +{ + int status; + + if (!adev) + return -ENOENT; + + status = acpi_get_handle(adev->handle, pathname, &aml_mutex); + if (ACPI_FAILURE(status)) + return -ENOENT; + + return 0; +} +EXPORT_SYMBOL(cros_ec_lpc_mec_acpi_mutex); diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.h b/drivers/platform/chrome/cros_ec_lpc_mec.h index 9d0521b23e8a..69f9d8786f61 100644 --- a/drivers/platform/chrome/cros_ec_lpc_mec.h +++ b/drivers/platform/chrome/cros_ec_lpc_mec.h @@ -8,6 +8,8 @@ #ifndef __CROS_EC_LPC_MEC_H #define __CROS_EC_LPC_MEC_H +#include <linux/acpi.h> + enum cros_ec_lpc_mec_emi_access_mode { /* 8-bit access */ ACCESS_TYPE_BYTE = 0x0, @@ -46,6 +48,15 @@ enum cros_ec_lpc_mec_io_type { void cros_ec_lpc_mec_init(unsigned int base, unsigned int end); /** + * cros_ec_lpc_mec_acpi_mutex() - Find and set ACPI mutex for MEC + * + * @adev: Parent ACPI device + * @pathname: Name of AML mutex + * @return: Negative error code, or zero for success + */ +int cros_ec_lpc_mec_acpi_mutex(struct acpi_device *adev, const char *pathname); + +/** * cros_ec_lpc_mec_in_range() - Determine if addresses are in MEC EMI range. * * @offset: Address offset @@ -64,9 +75,10 @@ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length); * @length: Number of bytes to read / write * @buf: Destination / source buffer * - * @return 8-bit checksum of all bytes read / written + * @return: A negative error code on error, or 8-bit checksum of all + * bytes read / written */ -u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, - unsigned int offset, unsigned int length, u8 *buf); +int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, + unsigned int offset, unsigned int length, u8 *buf); #endif /* __CROS_EC_LPC_MEC_H */ diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 945b1b15a04c..f776fd42244f 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -5,6 +5,7 @@ #include <linux/delay.h> #include <linux/device.h> +#include <linux/limits.h> #include <linux/module.h> #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> @@ -239,13 +240,12 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev, } EXPORT_SYMBOL(cros_ec_check_result); -/* +/** * cros_ec_get_host_event_wake_mask * * Get the mask of host events that cause wake from suspend. * * @ec_dev: EC device to call - * @msg: message structure to use * @mask: result when function returns 0. * * LOCKING: @@ -427,13 +427,12 @@ exit: return ret; } -/* +/** * cros_ec_get_host_command_version_mask * * Get the version mask of a given command. * * @ec_dev: EC device to call - * @msg: message structure to use * @cmd: command to get the version of. * @mask: result when function returns 0. * @@ -686,7 +685,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status); static int get_next_event_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg, - struct ec_response_get_next_event_v1 *event, + struct ec_response_get_next_event_v3 *event, int version, uint32_t size) { int ret; @@ -709,11 +708,12 @@ static int get_next_event(struct cros_ec_device *ec_dev) { struct { struct cros_ec_command msg; - struct ec_response_get_next_event_v1 event; + struct ec_response_get_next_event_v3 event; } __packed buf; struct cros_ec_command *msg = &buf.msg; - struct ec_response_get_next_event_v1 *event = &buf.event; - const int cmd_version = ec_dev->mkbp_event_supported - 1; + struct ec_response_get_next_event_v3 *event = &buf.event; + int cmd_version = ec_dev->mkbp_event_supported - 1; + u32 size; memset(msg, 0, sizeof(*msg)); if (ec_dev->suspended) { @@ -721,12 +721,20 @@ static int get_next_event(struct cros_ec_device *ec_dev) return -EHOSTDOWN; } - if (cmd_version == 0) - return get_next_event_xfer(ec_dev, msg, event, 0, - sizeof(struct ec_response_get_next_event)); + if (cmd_version == 0) { + size = sizeof(struct ec_response_get_next_event); + } else if (cmd_version < 3) { + size = sizeof(struct ec_response_get_next_event_v1); + } else { + /* + * The max version we support is v3. So, we speak v3 even if the + * EC says it supports v4+. + */ + cmd_version = 3; + size = sizeof(struct ec_response_get_next_event_v3); + } - return get_next_event_xfer(ec_dev, msg, event, cmd_version, - sizeof(struct ec_response_get_next_event_v1)); + return get_next_event_xfer(ec_dev, msg, event, cmd_version, size); } static int get_keyboard_state_event(struct cros_ec_device *ec_dev) @@ -1035,3 +1043,64 @@ error: return ret; } EXPORT_SYMBOL_GPL(cros_ec_cmd); + +/** + * cros_ec_cmd_readmem - Read from EC memory. + * + * @ec_dev: EC device + * @offset: Is within EC_LPC_ADDR_MEMMAP region. + * @size: Number of bytes to read. + * @dest: EC command output data + * + * Return: >= 0 on success, negative error number on failure. + */ +int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest) +{ + struct ec_params_read_memmap params = {}; + + if (!size) + return -EINVAL; + + if (ec_dev->cmd_readmem) + return ec_dev->cmd_readmem(ec_dev, offset, size, dest); + + params.offset = offset; + params.size = size; + return cros_ec_cmd(ec_dev, 0, EC_CMD_READ_MEMMAP, + ¶ms, sizeof(params), dest, size); +} +EXPORT_SYMBOL_GPL(cros_ec_cmd_readmem); + +/** + * cros_ec_get_cmd_versions - Get supported version mask. + * + * @ec_dev: EC device + * @cmd: Command to test + * + * Return: version mask on success, negative error number on failure. + */ +int cros_ec_get_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd) +{ + struct ec_params_get_cmd_versions req_v0; + struct ec_params_get_cmd_versions_v1 req_v1; + struct ec_response_get_cmd_versions resp; + int ret; + + if (cmd <= U8_MAX) { + req_v0.cmd = cmd; + ret = cros_ec_cmd(ec_dev, 0, EC_CMD_GET_CMD_VERSIONS, + &req_v0, sizeof(req_v0), &resp, sizeof(resp)); + } else { + req_v1.cmd = cmd; + ret = cros_ec_cmd(ec_dev, 1, EC_CMD_GET_CMD_VERSIONS, + &req_v1, sizeof(req_v1), &resp, sizeof(resp)); + } + + if (ret == -EINVAL) + return 0; /* Command not implemented */ + else if (ret < 0) + return ret; + else + return resp.version_mask; +} +EXPORT_SYMBOL_GPL(cros_ec_get_cmd_versions); diff --git a/drivers/platform/chrome/cros_ec_proto_test.c b/drivers/platform/chrome/cros_ec_proto_test.c index 41378c2ee6a0..7ca9895a0065 100644 --- a/drivers/platform/chrome/cros_ec_proto_test.c +++ b/drivers/platform/chrome/cros_ec_proto_test.c @@ -2060,17 +2060,17 @@ static void cros_ec_proto_test_get_next_event_no_mkbp_event(struct kunit *test) /* For get_keyboard_state_event(). */ { - union ec_response_get_next_data_v1 *data; + union ec_response_get_next_data_v3 *data; mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data)); KUNIT_ASSERT_PTR_NE(test, mock, NULL); - data = (union ec_response_get_next_data_v1 *)mock->o_data; + data = (union ec_response_get_next_data_v3 *)mock->o_data; data->host_event = 0xbeef; } ret = cros_ec_get_next_event(ec_dev, &wake_event, &more_events); - KUNIT_EXPECT_EQ(test, ret, sizeof(union ec_response_get_next_data_v1)); + KUNIT_EXPECT_EQ(test, ret, sizeof(union ec_response_get_next_data_v3)); KUNIT_EXPECT_EQ(test, ec_dev->event_data.event_type, EC_MKBP_EVENT_KEY_MATRIX); KUNIT_EXPECT_EQ(test, ec_dev->event_data.data.host_event, 0xbeef); @@ -2085,7 +2085,7 @@ static void cros_ec_proto_test_get_next_event_no_mkbp_event(struct kunit *test) KUNIT_EXPECT_EQ(test, mock->msg.version, 0); KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_MKBP_STATE); - KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(union ec_response_get_next_data_v1)); + KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(union ec_response_get_next_data_v3)); KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0); } } @@ -2740,4 +2740,5 @@ static struct kunit_suite cros_ec_proto_test_suite = { kunit_test_suite(cros_ec_proto_test_suite); +MODULE_DESCRIPTION("Kunit tests for ChromeOS Embedded Controller protocol"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/chrome/wilco_ec/mailbox.c b/drivers/platform/chrome/wilco_ec/mailbox.c index 0f98358ea824..4d8273b47cde 100644 --- a/drivers/platform/chrome/wilco_ec/mailbox.c +++ b/drivers/platform/chrome/wilco_ec/mailbox.c @@ -117,13 +117,17 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec, struct wilco_ec_request *rq) { struct wilco_ec_response *rs; - u8 checksum; + int ret; u8 flag; /* Write request header, then data */ - cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq); - cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size, - msg->request_data); + ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq); + if (ret < 0) + return ret; + ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size, + msg->request_data); + if (ret < 0) + return ret; /* Start the command */ outb(EC_MAILBOX_START_COMMAND, ec->io_command->start); @@ -149,10 +153,12 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec, /* Read back response */ rs = ec->data_buffer; - checksum = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0, - sizeof(*rs) + EC_MAILBOX_DATA_SIZE, - (u8 *)rs); - if (checksum) { + ret = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0, + sizeof(*rs) + EC_MAILBOX_DATA_SIZE, + (u8 *)rs); + if (ret < 0) + return ret; + if (ret) { dev_dbg(ec->dev, "bad packet checksum 0x%02x\n", rs->checksum); return -EBADMSG; } diff --git a/drivers/platform/mellanox/nvsw-sn2201.c b/drivers/platform/mellanox/nvsw-sn2201.c index 3ef655591424..abe7be602f84 100644 --- a/drivers/platform/mellanox/nvsw-sn2201.c +++ b/drivers/platform/mellanox/nvsw-sn2201.c @@ -1198,6 +1198,7 @@ static int nvsw_sn2201_config_pre_init(struct nvsw_sn2201 *nvsw_sn2201) static int nvsw_sn2201_probe(struct platform_device *pdev) { struct nvsw_sn2201 *nvsw_sn2201; + int ret; nvsw_sn2201 = devm_kzalloc(&pdev->dev, sizeof(*nvsw_sn2201), GFP_KERNEL); if (!nvsw_sn2201) @@ -1205,8 +1206,10 @@ static int nvsw_sn2201_probe(struct platform_device *pdev) nvsw_sn2201->dev = &pdev->dev; platform_set_drvdata(pdev, nvsw_sn2201); - platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources, + ret = platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources, ARRAY_SIZE(nvsw_sn2201_lpc_io_resources)); + if (ret) + return ret; nvsw_sn2201->main_mux_deferred_nr = NVSW_SN2201_MAIN_MUX_DEFER_NR; nvsw_sn2201->main_mux_devs = nvsw_sn2201_main_mux_brdinfo; diff --git a/drivers/platform/x86/amilo-rfkill.c b/drivers/platform/x86/amilo-rfkill.c index efcf909786a5..2423dc91debb 100644 --- a/drivers/platform/x86/amilo-rfkill.c +++ b/drivers/platform/x86/amilo-rfkill.c @@ -171,6 +171,7 @@ static void __exit amilo_rfkill_exit(void) } MODULE_AUTHOR("Ben Hutchings <ben@decadent.org.uk>"); +MODULE_DESCRIPTION("Fujitsu-Siemens Amilo rfkill support"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(dmi, amilo_rfkill_id_table); diff --git a/drivers/platform/x86/firmware_attributes_class.c b/drivers/platform/x86/firmware_attributes_class.c index dd8240009565..182a07d8ae3d 100644 --- a/drivers/platform/x86/firmware_attributes_class.c +++ b/drivers/platform/x86/firmware_attributes_class.c @@ -49,4 +49,5 @@ int fw_attributes_class_put(void) EXPORT_SYMBOL_GPL(fw_attributes_class_put); MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); +MODULE_DESCRIPTION("Firmware attributes class helper module"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index 1d4bbae115f1..231b37909801 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c @@ -29,6 +29,7 @@ static bool debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Show debug output"); +MODULE_DESCRIPTION("IBM Premium Real Time Mode (PRTM) driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>"); MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>"); diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c index c7a827645864..10cd65497cc1 100644 --- a/drivers/platform/x86/intel/hid.c +++ b/drivers/platform/x86/intel/hid.c @@ -38,6 +38,7 @@ MODULE_PARM_DESC(enable_sw_tablet_mode, /* When NOT in tablet mode, VGBS returns with the flag 0x40 */ #define TABLET_MODE_FLAG BIT(6) +MODULE_DESCRIPTION("Intel HID Event hotkey driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alex Hung"); diff --git a/drivers/platform/x86/intel/pmc/pltdrv.c b/drivers/platform/x86/intel/pmc/pltdrv.c index ddfba38c2104..f2cb87dc2d37 100644 --- a/drivers/platform/x86/intel/pmc/pltdrv.c +++ b/drivers/platform/x86/intel/pmc/pltdrv.c @@ -86,4 +86,5 @@ static void __exit pmc_core_platform_exit(void) module_init(pmc_core_platform_init); module_exit(pmc_core_platform_exit); +MODULE_DESCRIPTION("Intel PMC Core platform driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/intel/rst.c b/drivers/platform/x86/intel/rst.c index 6bc9c4a603e0..f3a60e14d4c1 100644 --- a/drivers/platform/x86/intel/rst.c +++ b/drivers/platform/x86/intel/rst.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/slab.h> +MODULE_DESCRIPTION("Intel Rapid Start Technology Driver"); MODULE_LICENSE("GPL"); static ssize_t irst_show_wakeup_events(struct device *dev, diff --git a/drivers/platform/x86/intel/smartconnect.c b/drivers/platform/x86/intel/smartconnect.c index cd25d0585324..31019a1a6d5e 100644 --- a/drivers/platform/x86/intel/smartconnect.c +++ b/drivers/platform/x86/intel/smartconnect.c @@ -6,6 +6,7 @@ #include <linux/acpi.h> #include <linux/module.h> +MODULE_DESCRIPTION("Intel Smart Connect disabling driver"); MODULE_LICENSE("GPL"); static int smartconnect_acpi_init(struct acpi_device *acpi) diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c index 84c1353eb12b..9b7ce03ba085 100644 --- a/drivers/platform/x86/intel/vbtn.c +++ b/drivers/platform/x86/intel/vbtn.c @@ -24,6 +24,7 @@ #define VGBS_TABLET_MODE_FLAGS (VGBS_TABLET_MODE_FLAG | VGBS_TABLET_MODE_FLAG_ALT) +MODULE_DESCRIPTION("Intel Virtual Button driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("AceLan Kao"); diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c index d0fee5d375d7..9c7857842caf 100644 --- a/drivers/platform/x86/lg-laptop.c +++ b/drivers/platform/x86/lg-laptop.c @@ -39,8 +39,6 @@ MODULE_LICENSE("GPL"); #define WMI_METHOD_WMBB "2B4F501A-BD3C-4394-8DCF-00A7D2BC8210" #define WMI_EVENT_GUID WMI_EVENT_GUID0 -#define WMAB_METHOD "\\XINI.WMAB" -#define WMBB_METHOD "\\XINI.WMBB" #define SB_GGOV_METHOD "\\_SB.GGOV" #define GOV_TLED 0x2020008 #define WM_GET 1 @@ -74,7 +72,7 @@ static u32 inited; static int battery_limit_use_wmbb; static struct led_classdev kbd_backlight; -static enum led_brightness get_kbd_backlight_level(void); +static enum led_brightness get_kbd_backlight_level(struct device *dev); static const struct key_entry wmi_keymap[] = { {KE_KEY, 0x70, {KEY_F15} }, /* LG control panel (F1) */ @@ -84,7 +82,6 @@ static const struct key_entry wmi_keymap[] = { * this key both sends an event and * changes backlight level. */ - {KE_KEY, 0x80, {KEY_RFKILL} }, {KE_END, 0} }; @@ -128,11 +125,10 @@ static int ggov(u32 arg0) return res; } -static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2) +static union acpi_object *lg_wmab(struct device *dev, u32 method, u32 arg1, u32 arg2) { union acpi_object args[3]; acpi_status status; - acpi_handle handle; struct acpi_object_list arg; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -143,29 +139,22 @@ static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2) args[2].type = ACPI_TYPE_INTEGER; args[2].integer.value = arg2; - status = acpi_get_handle(NULL, (acpi_string) WMAB_METHOD, &handle); - if (ACPI_FAILURE(status)) { - pr_err("Cannot get handle"); - return NULL; - } - arg.count = 3; arg.pointer = args; - status = acpi_evaluate_object(handle, NULL, &arg, &buffer); + status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMAB", &arg, &buffer); if (ACPI_FAILURE(status)) { - acpi_handle_err(handle, "WMAB: call failed.\n"); + dev_err(dev, "WMAB: call failed.\n"); return NULL; } return buffer.pointer; } -static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2) +static union acpi_object *lg_wmbb(struct device *dev, u32 method_id, u32 arg1, u32 arg2) { union acpi_object args[3]; acpi_status status; - acpi_handle handle; struct acpi_object_list arg; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; u8 buf[32]; @@ -181,18 +170,12 @@ static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2) args[2].buffer.length = 32; args[2].buffer.pointer = buf; - status = acpi_get_handle(NULL, (acpi_string)WMBB_METHOD, &handle); - if (ACPI_FAILURE(status)) { - pr_err("Cannot get handle"); - return NULL; - } - arg.count = 3; arg.pointer = args; - status = acpi_evaluate_object(handle, NULL, &arg, &buffer); + status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMBB", &arg, &buffer); if (ACPI_FAILURE(status)) { - acpi_handle_err(handle, "WMAB: call failed.\n"); + dev_err(dev, "WMBB: call failed.\n"); return NULL; } @@ -223,7 +206,7 @@ static void wmi_notify(u32 value, void *context) if (eventcode == 0x10000000) { led_classdev_notify_brightness_hw_changed( - &kbd_backlight, get_kbd_backlight_level()); + &kbd_backlight, get_kbd_backlight_level(kbd_backlight.dev->parent)); } else { key = sparse_keymap_entry_from_scancode( wmi_input_dev, eventcode); @@ -272,14 +255,7 @@ static void wmi_input_setup(void) static void acpi_notify(struct acpi_device *device, u32 event) { - struct key_entry *key; - acpi_handle_debug(device->handle, "notify: %d\n", event); - if (inited & INIT_SPARSE_KEYMAP) { - key = sparse_keymap_entry_from_scancode(wmi_input_dev, 0x80); - if (key && key->type == KE_KEY) - sparse_keymap_report_entry(wmi_input_dev, key, 1, true); - } } static ssize_t fan_mode_store(struct device *dev, @@ -295,7 +271,7 @@ static ssize_t fan_mode_store(struct device *dev, if (ret) return ret; - r = lg_wmab(WM_FAN_MODE, WM_GET, 0); + r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0); if (!r) return -EIO; @@ -306,9 +282,9 @@ static ssize_t fan_mode_store(struct device *dev, m = r->integer.value; kfree(r); - r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4)); + r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4)); kfree(r); - r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value); + r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value); kfree(r); return count; @@ -320,7 +296,7 @@ static ssize_t fan_mode_show(struct device *dev, unsigned int status; union acpi_object *r; - r = lg_wmab(WM_FAN_MODE, WM_GET, 0); + r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0); if (!r) return -EIO; @@ -347,7 +323,7 @@ static ssize_t usb_charge_store(struct device *dev, if (ret) return ret; - r = lg_wmbb(WMBB_USB_CHARGE, WM_SET, value); + r = lg_wmbb(dev, WMBB_USB_CHARGE, WM_SET, value); if (!r) return -EIO; @@ -361,7 +337,7 @@ static ssize_t usb_charge_show(struct device *dev, unsigned int status; union acpi_object *r; - r = lg_wmbb(WMBB_USB_CHARGE, WM_GET, 0); + r = lg_wmbb(dev, WMBB_USB_CHARGE, WM_GET, 0); if (!r) return -EIO; @@ -389,7 +365,7 @@ static ssize_t reader_mode_store(struct device *dev, if (ret) return ret; - r = lg_wmab(WM_READER_MODE, WM_SET, value); + r = lg_wmab(dev, WM_READER_MODE, WM_SET, value); if (!r) return -EIO; @@ -403,7 +379,7 @@ static ssize_t reader_mode_show(struct device *dev, unsigned int status; union acpi_object *r; - r = lg_wmab(WM_READER_MODE, WM_GET, 0); + r = lg_wmab(dev, WM_READER_MODE, WM_GET, 0); if (!r) return -EIO; @@ -431,7 +407,7 @@ static ssize_t fn_lock_store(struct device *dev, if (ret) return ret; - r = lg_wmab(WM_FN_LOCK, WM_SET, value); + r = lg_wmab(dev, WM_FN_LOCK, WM_SET, value); if (!r) return -EIO; @@ -445,7 +421,7 @@ static ssize_t fn_lock_show(struct device *dev, unsigned int status; union acpi_object *r; - r = lg_wmab(WM_FN_LOCK, WM_GET, 0); + r = lg_wmab(dev, WM_FN_LOCK, WM_GET, 0); if (!r) return -EIO; @@ -475,9 +451,9 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, union acpi_object *r; if (battery_limit_use_wmbb) - r = lg_wmbb(WMBB_BATT_LIMIT, WM_SET, value); + r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_SET, value); else - r = lg_wmab(WM_BATT_LIMIT, WM_SET, value); + r = lg_wmab(&pf_device->dev, WM_BATT_LIMIT, WM_SET, value); if (!r) return -EIO; @@ -496,7 +472,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device, union acpi_object *r; if (battery_limit_use_wmbb) { - r = lg_wmbb(WMBB_BATT_LIMIT, WM_GET, 0); + r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_GET, 0); if (!r) return -EIO; @@ -507,7 +483,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device, status = r->buffer.pointer[0x10]; } else { - r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0); + r = lg_wmab(&pf_device->dev, WM_BATT_LIMIT, WM_GET, 0); if (!r) return -EIO; @@ -586,7 +562,7 @@ static void tpad_led_set(struct led_classdev *cdev, { union acpi_object *r; - r = lg_wmab(WM_TLED, WM_SET, brightness > LED_OFF); + r = lg_wmab(cdev->dev->parent, WM_TLED, WM_SET, brightness > LED_OFF); kfree(r); } @@ -608,16 +584,16 @@ static void kbd_backlight_set(struct led_classdev *cdev, val = 0; if (brightness >= LED_FULL) val = 0x24; - r = lg_wmab(WM_KEY_LIGHT, WM_SET, val); + r = lg_wmab(cdev->dev->parent, WM_KEY_LIGHT, WM_SET, val); kfree(r); } -static enum led_brightness get_kbd_backlight_level(void) +static enum led_brightness get_kbd_backlight_level(struct device *dev) { union acpi_object *r; int val; - r = lg_wmab(WM_KEY_LIGHT, WM_GET, 0); + r = lg_wmab(dev, WM_KEY_LIGHT, WM_GET, 0); if (!r) return LED_OFF; @@ -645,7 +621,7 @@ static enum led_brightness get_kbd_backlight_level(void) static enum led_brightness kbd_backlight_get(struct led_classdev *cdev) { - return get_kbd_backlight_level(); + return get_kbd_backlight_level(cdev->dev->parent); } static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED); @@ -672,6 +648,11 @@ static struct platform_driver pf_driver = { static int acpi_add(struct acpi_device *device) { + struct platform_device_info pdev_info = { + .fwnode = acpi_fwnode_handle(device), + .name = PLATFORM_NAME, + .id = PLATFORM_DEVID_NONE, + }; int ret; const char *product; int year = 2017; @@ -683,9 +664,7 @@ static int acpi_add(struct acpi_device *device) if (ret) return ret; - pf_device = platform_device_register_simple(PLATFORM_NAME, - PLATFORM_DEVID_NONE, - NULL, 0); + pf_device = platform_device_register_full(&pdev_info); if (IS_ERR(pf_device)) { ret = PTR_ERR(pf_device); pf_device = NULL; @@ -776,7 +755,7 @@ static void acpi_remove(struct acpi_device *device) } static const struct acpi_device_id device_ids[] = { - {"LGEX0815", 0}, + {"LGEX0820", 0}, {"", 0} }; MODULE_DEVICE_TABLE(acpi, device_ids); diff --git a/drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c b/drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c index 31a139d87d9a..5edc294de6e4 100644 --- a/drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c +++ b/drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c @@ -45,6 +45,7 @@ static struct platform_driver simatic_ipc_batt_driver = { module_platform_driver(simatic_ipc_batt_driver); +MODULE_DESCRIPTION("CMOS Battery monitoring for Simatic IPCs based on Apollo Lake GPIO"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" KBUILD_MODNAME); MODULE_SOFTDEP("pre: simatic-ipc-batt platform:apollolake-pinctrl"); diff --git a/drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c b/drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c index a7676f224075..e6a56d14b505 100644 --- a/drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c +++ b/drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c @@ -45,6 +45,7 @@ static struct platform_driver simatic_ipc_batt_driver = { module_platform_driver(simatic_ipc_batt_driver); +MODULE_DESCRIPTION("CMOS Battery monitoring for Simatic IPCs based on Elkhart Lake GPIO"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" KBUILD_MODNAME); MODULE_SOFTDEP("pre: simatic-ipc-batt platform:elkhartlake-pinctrl"); diff --git a/drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c b/drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c index 5e77e05fdb5d..f8849d0e48a8 100644 --- a/drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c +++ b/drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c @@ -81,6 +81,7 @@ static struct platform_driver simatic_ipc_batt_driver = { module_platform_driver(simatic_ipc_batt_driver); +MODULE_DESCRIPTION("CMOS Battery monitoring for Simatic IPCs based on Nuvoton GPIO"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" KBUILD_MODNAME); MODULE_SOFTDEP("pre: simatic-ipc-batt gpio_f7188x platform:elkhartlake-pinctrl platform:alderlake-pinctrl"); diff --git a/drivers/platform/x86/siemens/simatic-ipc-batt.c b/drivers/platform/x86/siemens/simatic-ipc-batt.c index c6dd263b4ee3..d9aff10608cf 100644 --- a/drivers/platform/x86/siemens/simatic-ipc-batt.c +++ b/drivers/platform/x86/siemens/simatic-ipc-batt.c @@ -247,6 +247,7 @@ static struct platform_driver simatic_ipc_batt_driver = { module_platform_driver(simatic_ipc_batt_driver); +MODULE_DESCRIPTION("CMOS core battery driver for Siemens Simatic IPCs"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" KBUILD_MODNAME); MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>"); diff --git a/drivers/platform/x86/siemens/simatic-ipc.c b/drivers/platform/x86/siemens/simatic-ipc.c index 8ca6e277fa03..7039874d8f11 100644 --- a/drivers/platform/x86/siemens/simatic-ipc.c +++ b/drivers/platform/x86/siemens/simatic-ipc.c @@ -231,6 +231,7 @@ static void __exit simatic_ipc_exit_module(void) module_init(simatic_ipc_init_module); module_exit(simatic_ipc_exit_module); +MODULE_DESCRIPTION("Siemens SIMATIC IPC platform driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Gerd Haeussler <gerd.haeussler.ext@siemens.com>"); MODULE_ALIAS("dmi:*:svnSIEMENSAG:*"); diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 3a8d8df89186..78a5aac2dcfd 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -3271,7 +3271,7 @@ static const char *find_hci_method(acpi_handle handle) */ #define QUIRK_HCI_HOTKEY_QUICKSTART BIT(1) -static const struct dmi_system_id toshiba_dmi_quirks[] = { +static const struct dmi_system_id toshiba_dmi_quirks[] __initconst = { { /* Toshiba Portégé R700 */ /* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */ @@ -3299,6 +3299,7 @@ static const struct dmi_system_id toshiba_dmi_quirks[] = { }, .driver_data = (void *)(QUIRK_TURN_ON_PANEL_ON_RESUME | QUIRK_HCI_HOTKEY_QUICKSTART), }, + { } }; static int toshiba_acpi_add(struct acpi_device *acpi_dev) @@ -3306,8 +3307,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) struct toshiba_acpi_dev *dev; const char *hci_method; u32 dummy; - const struct dmi_system_id *dmi_id; - long quirks = 0; int ret = 0; if (toshiba_acpi) @@ -3460,16 +3459,6 @@ iio_error: } #endif - dmi_id = dmi_first_match(toshiba_dmi_quirks); - if (dmi_id) - quirks = (long)dmi_id->driver_data; - - if (turn_on_panel_on_resume == -1) - turn_on_panel_on_resume = !!(quirks & QUIRK_TURN_ON_PANEL_ON_RESUME); - - if (hci_hotkey_quickstart == -1) - hci_hotkey_quickstart = !!(quirks & QUIRK_HCI_HOTKEY_QUICKSTART); - toshiba_wwan_available(dev); if (dev->wwan_supported) toshiba_acpi_setup_wwan_rfkill(dev); @@ -3618,10 +3607,27 @@ static struct acpi_driver toshiba_acpi_driver = { .drv.pm = &toshiba_acpi_pm, }; +static void __init toshiba_dmi_init(void) +{ + const struct dmi_system_id *dmi_id; + long quirks = 0; + + dmi_id = dmi_first_match(toshiba_dmi_quirks); + if (dmi_id) + quirks = (long)dmi_id->driver_data; + + if (turn_on_panel_on_resume == -1) + turn_on_panel_on_resume = !!(quirks & QUIRK_TURN_ON_PANEL_ON_RESUME); + + if (hci_hotkey_quickstart == -1) + hci_hotkey_quickstart = !!(quirks & QUIRK_HCI_HOTKEY_QUICKSTART); +} + static int __init toshiba_acpi_init(void) { int ret; + toshiba_dmi_init(); toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); if (!toshiba_proc_dir) { pr_err("Unable to create proc dir " PROC_TOSHIBA "\n"); diff --git a/drivers/platform/x86/uv_sysfs.c b/drivers/platform/x86/uv_sysfs.c index 37372d7cc54a..f6a0627f36db 100644 --- a/drivers/platform/x86/uv_sysfs.c +++ b/drivers/platform/x86/uv_sysfs.c @@ -929,4 +929,5 @@ module_init(uv_sysfs_init); module_exit(uv_sysfs_exit); MODULE_AUTHOR("Hewlett Packard Enterprise"); +MODULE_DESCRIPTION("Sysfs structure for HPE UV systems"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/wireless-hotkey.c b/drivers/platform/x86/wireless-hotkey.c index e95cdbbfb708..a220fe4f9ef8 100644 --- a/drivers/platform/x86/wireless-hotkey.c +++ b/drivers/platform/x86/wireless-hotkey.c @@ -14,11 +14,13 @@ #include <linux/acpi.h> #include <acpi/acpi_bus.h> +MODULE_DESCRIPTION("Airplane mode button for AMD, HP & Xiaomi laptops"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alex Hung"); MODULE_ALIAS("acpi*:HPQ6001:*"); MODULE_ALIAS("acpi*:WSTADEF:*"); MODULE_ALIAS("acpi*:AMDI0051:*"); +MODULE_ALIAS("acpi*:LGEX0815:*"); struct wl_button { struct input_dev *input_dev; @@ -29,6 +31,7 @@ static const struct acpi_device_id wl_ids[] = { {"HPQ6001", 0}, {"WSTADEF", 0}, {"AMDI0051", 0}, + {"LGEX0815", 0}, {"", 0}, }; diff --git a/drivers/platform/x86/xo1-rfkill.c b/drivers/platform/x86/xo1-rfkill.c index e64d5646b4c7..5fe68296501c 100644 --- a/drivers/platform/x86/xo1-rfkill.c +++ b/drivers/platform/x86/xo1-rfkill.c @@ -74,5 +74,6 @@ static struct platform_driver xo1_rfkill_driver = { module_platform_driver(xo1_rfkill_driver); MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); +MODULE_DESCRIPTION("OLPC XO-1 software RF kill switch"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:xo1-rfkill"); |
