diff options
Diffstat (limited to 'drivers/platform/chrome/cros_ec_sysfs.c')
| -rw-r--r-- | drivers/platform/chrome/cros_ec_sysfs.c | 124 |
1 files changed, 96 insertions, 28 deletions
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index f07eabcf9494..f22e9523da3e 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -8,6 +8,7 @@ #include <linux/device.h> #include <linux/fs.h> #include <linux/kobject.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> @@ -27,10 +28,9 @@ static ssize_t reboot_show(struct device *dev, { int count = 0; - count += scnprintf(buf + count, PAGE_SIZE - count, - "ro|rw|cancel|cold|disable-jump|hibernate|cold-ap-off"); - count += scnprintf(buf + count, PAGE_SIZE - count, - " [at-shutdown]\n"); + count += sysfs_emit_at(buf, count, + "ro|rw|cancel|cold|disable-jump|hibernate|cold-ap-off"); + count += sysfs_emit_at(buf, count, " [at-shutdown]\n"); return count; } @@ -138,12 +138,9 @@ static ssize_t version_show(struct device *dev, /* Strings should be null-terminated, but let's be sure. */ r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0'; r_ver->version_string_rw[sizeof(r_ver->version_string_rw) - 1] = '\0'; - count += scnprintf(buf + count, PAGE_SIZE - count, - "RO version: %s\n", r_ver->version_string_ro); - count += scnprintf(buf + count, PAGE_SIZE - count, - "RW version: %s\n", r_ver->version_string_rw); - count += scnprintf(buf + count, PAGE_SIZE - count, - "Firmware copy: %s\n", + count += sysfs_emit_at(buf, count, "RO version: %s\n", r_ver->version_string_ro); + count += sysfs_emit_at(buf, count, "RW version: %s\n", r_ver->version_string_rw); + count += sysfs_emit_at(buf, count, "Firmware copy: %s\n", (r_ver->current_image < ARRAY_SIZE(image_names) ? image_names[r_ver->current_image] : "?")); @@ -152,13 +149,12 @@ static ssize_t version_show(struct device *dev, msg->insize = EC_HOST_PARAM_SIZE; ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { - count += scnprintf(buf + count, PAGE_SIZE - count, + count += sysfs_emit_at(buf, count, "Build info: XFER / EC ERROR %d / %d\n", ret, msg->result); } else { msg->data[EC_HOST_PARAM_SIZE - 1] = '\0'; - count += scnprintf(buf + count, PAGE_SIZE - count, - "Build info: %s\n", msg->data); + count += sysfs_emit_at(buf, count, "Build info: %s\n", msg->data); } /* Get chip info. */ @@ -166,7 +162,7 @@ static ssize_t version_show(struct device *dev, msg->insize = sizeof(*r_chip); ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { - count += scnprintf(buf + count, PAGE_SIZE - count, + count += sysfs_emit_at(buf, count, "Chip info: XFER / EC ERROR %d / %d\n", ret, msg->result); } else { @@ -175,12 +171,9 @@ static ssize_t version_show(struct device *dev, r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0'; r_chip->name[sizeof(r_chip->name) - 1] = '\0'; r_chip->revision[sizeof(r_chip->revision) - 1] = '\0'; - count += scnprintf(buf + count, PAGE_SIZE - count, - "Chip vendor: %s\n", r_chip->vendor); - count += scnprintf(buf + count, PAGE_SIZE - count, - "Chip name: %s\n", r_chip->name); - count += scnprintf(buf + count, PAGE_SIZE - count, - "Chip revision: %s\n", r_chip->revision); + count += sysfs_emit_at(buf, count, "Chip vendor: %s\n", r_chip->vendor); + count += sysfs_emit_at(buf, count, "Chip name: %s\n", r_chip->name); + count += sysfs_emit_at(buf, count, "Chip revision: %s\n", r_chip->revision); } /* Get board version */ @@ -188,13 +181,13 @@ static ssize_t version_show(struct device *dev, msg->insize = sizeof(*r_board); ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { - count += scnprintf(buf + count, PAGE_SIZE - count, + count += sysfs_emit_at(buf, count, "Board version: XFER / EC ERROR %d / %d\n", ret, msg->result); } else { r_board = (struct ec_response_board_version *)msg->data; - count += scnprintf(buf + count, PAGE_SIZE - count, + count += sysfs_emit_at(buf, count, "Board version: %d\n", r_board->board_version); } @@ -227,7 +220,7 @@ static ssize_t flashinfo_show(struct device *dev, resp = (struct ec_response_flash_info *)msg->data; - ret = scnprintf(buf, PAGE_SIZE, + ret = sysfs_emit(buf, "FlashSize %d\nWriteSize %d\n" "EraseSize %d\nProtectSize %d\n", resp->flash_size, resp->write_block_size, @@ -264,7 +257,7 @@ static ssize_t kb_wake_angle_show(struct device *dev, goto exit; resp = (struct ec_response_motion_sense *)msg->data; - ret = scnprintf(buf, PAGE_SIZE, "%d\n", resp->kb_wake_angle.ret); + ret = sysfs_emit(buf, "%d\n", resp->kb_wake_angle.ret); exit: kfree(msg); return ret; @@ -303,18 +296,81 @@ static ssize_t kb_wake_angle_store(struct device *dev, return count; } +static ssize_t usbpdmuxinfo_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + ssize_t count = 0; + struct ec_response_usb_pd_ports resp_pd_ports; + int ret; + int i; + + ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_USB_PD_PORTS, NULL, 0, + &resp_pd_ports, sizeof(resp_pd_ports)); + if (ret < 0) + return -EIO; + + for (i = 0; i < resp_pd_ports.num_ports; i++) { + struct ec_response_usb_pd_mux_info resp_mux; + struct ec_params_usb_pd_mux_info req = { + .port = i, + }; + + ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_USB_PD_MUX_INFO, + &req, sizeof(req), &resp_mux, sizeof(resp_mux)); + + if (ret >= 0) { + count += sysfs_emit_at(buf, count, "Port %d:", i); + count += sysfs_emit_at(buf, count, " USB=%d", + !!(resp_mux.flags & USB_PD_MUX_USB_ENABLED)); + count += sysfs_emit_at(buf, count, " DP=%d", + !!(resp_mux.flags & USB_PD_MUX_DP_ENABLED)); + count += sysfs_emit_at(buf, count, " POLARITY=%s", + (resp_mux.flags & USB_PD_MUX_POLARITY_INVERTED) ? + "INVERTED" : "NORMAL"); + count += sysfs_emit_at(buf, count, " HPD_IRQ=%d", + !!(resp_mux.flags & USB_PD_MUX_HPD_IRQ)); + count += sysfs_emit_at(buf, count, " HPD_LVL=%d", + !!(resp_mux.flags & USB_PD_MUX_HPD_LVL)); + count += sysfs_emit_at(buf, count, " SAFE=%d", + !!(resp_mux.flags & USB_PD_MUX_SAFE_MODE)); + count += sysfs_emit_at(buf, count, " TBT=%d", + !!(resp_mux.flags & USB_PD_MUX_TBT_COMPAT_ENABLED)); + count += sysfs_emit_at(buf, count, " USB4=%d\n", + !!(resp_mux.flags & USB_PD_MUX_USB4_ENABLED)); + } + } + + return count ? : -EIO; +} + +static ssize_t ap_mode_entry_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + const bool ap_driven_altmode = cros_ec_check_features( + ec, EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY); + + return sysfs_emit(buf, "%s\n", ap_driven_altmode ? "yes" : "no"); +} + /* Module initialization */ static DEVICE_ATTR_RW(reboot); static DEVICE_ATTR_RO(version); static DEVICE_ATTR_RO(flashinfo); static DEVICE_ATTR_RW(kb_wake_angle); +static DEVICE_ATTR_RO(usbpdmuxinfo); +static DEVICE_ATTR_RO(ap_mode_entry); static struct attribute *__ec_attrs[] = { &dev_attr_kb_wake_angle.attr, &dev_attr_reboot.attr, &dev_attr_version.attr, &dev_attr_flashinfo.attr, + &dev_attr_usbpdmuxinfo.attr, + &dev_attr_ap_mode_entry.attr, NULL, }; @@ -327,6 +383,14 @@ static umode_t cros_ec_ctrl_visible(struct kobject *kobj, if (a == &dev_attr_kb_wake_angle.attr && !ec->has_kb_wake_angle) return 0; + if (a == &dev_attr_usbpdmuxinfo.attr || + a == &dev_attr_ap_mode_entry.attr) { + struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); + + if (strcmp(ec_platform->ec_name, CROS_EC_DEV_NAME)) + return 0; + } + return a->mode; } @@ -348,25 +412,29 @@ static int cros_ec_sysfs_probe(struct platform_device *pd) return ret; } -static int cros_ec_sysfs_remove(struct platform_device *pd) +static void cros_ec_sysfs_remove(struct platform_device *pd) { struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); sysfs_remove_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group); - - return 0; } +static const struct platform_device_id cros_ec_sysfs_id[] = { + { DRV_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, cros_ec_sysfs_id); + static struct platform_driver cros_ec_sysfs_driver = { .driver = { .name = DRV_NAME, }, .probe = cros_ec_sysfs_probe, .remove = cros_ec_sysfs_remove, + .id_table = cros_ec_sysfs_id, }; module_platform_driver(cros_ec_sysfs_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Expose the ChromeOS EC through sysfs"); -MODULE_ALIAS("platform:" DRV_NAME); |
