linux/drivers/platform/chrome/wilco_ec/sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2019 Google LLC
   4 *
   5 * Sysfs properties to view and modify EC-controlled features on Wilco devices.
   6 * The entries will appear under /sys/bus/platform/devices/GOOG000C:00/
   7 *
   8 * See Documentation/ABI/testing/sysfs-platform-wilco-ec for more information.
   9 */
  10
  11#include <linux/platform_data/wilco-ec.h>
  12#include <linux/sysfs.h>
  13
  14#define CMD_KB_CMOS                     0x7C
  15#define SUB_CMD_KB_CMOS_AUTO_ON         0x03
  16
  17struct boot_on_ac_request {
  18        u8 cmd;                 /* Always CMD_KB_CMOS */
  19        u8 reserved1;
  20        u8 sub_cmd;             /* Always SUB_CMD_KB_CMOS_AUTO_ON */
  21        u8 reserved3to5[3];
  22        u8 val;                 /* Either 0 or 1 */
  23        u8 reserved7;
  24} __packed;
  25
  26#define CMD_EC_INFO                     0x38
  27enum get_ec_info_op {
  28        CMD_GET_EC_LABEL        = 0,
  29        CMD_GET_EC_REV          = 1,
  30        CMD_GET_EC_MODEL        = 2,
  31        CMD_GET_EC_BUILD_DATE   = 3,
  32};
  33
  34struct get_ec_info_req {
  35        u8 cmd;                 /* Always CMD_EC_INFO */
  36        u8 reserved;
  37        u8 op;                  /* One of enum get_ec_info_op */
  38} __packed;
  39
  40struct get_ec_info_resp {
  41        u8 reserved[2];
  42        char value[9]; /* __nonstring: might not be null terminated */
  43} __packed;
  44
  45static ssize_t boot_on_ac_store(struct device *dev,
  46                                struct device_attribute *attr,
  47                                const char *buf, size_t count)
  48{
  49        struct wilco_ec_device *ec = dev_get_drvdata(dev);
  50        struct boot_on_ac_request rq;
  51        struct wilco_ec_message msg;
  52        int ret;
  53        u8 val;
  54
  55        ret = kstrtou8(buf, 10, &val);
  56        if (ret < 0)
  57                return ret;
  58        if (val > 1)
  59                return -EINVAL;
  60
  61        memset(&rq, 0, sizeof(rq));
  62        rq.cmd = CMD_KB_CMOS;
  63        rq.sub_cmd = SUB_CMD_KB_CMOS_AUTO_ON;
  64        rq.val = val;
  65
  66        memset(&msg, 0, sizeof(msg));
  67        msg.type = WILCO_EC_MSG_LEGACY;
  68        msg.request_data = &rq;
  69        msg.request_size = sizeof(rq);
  70        ret = wilco_ec_mailbox(ec, &msg);
  71        if (ret < 0)
  72                return ret;
  73
  74        return count;
  75}
  76
  77static DEVICE_ATTR_WO(boot_on_ac);
  78
  79static ssize_t get_info(struct device *dev, char *buf, enum get_ec_info_op op)
  80{
  81        struct wilco_ec_device *ec = dev_get_drvdata(dev);
  82        struct get_ec_info_req req = { .cmd = CMD_EC_INFO, .op = op };
  83        struct get_ec_info_resp resp;
  84        int ret;
  85
  86        struct wilco_ec_message msg = {
  87                .type = WILCO_EC_MSG_LEGACY,
  88                .request_data = &req,
  89                .request_size = sizeof(req),
  90                .response_data = &resp,
  91                .response_size = sizeof(resp),
  92        };
  93
  94        ret = wilco_ec_mailbox(ec, &msg);
  95        if (ret < 0)
  96                return ret;
  97
  98        return scnprintf(buf, PAGE_SIZE, "%.*s\n", (int)sizeof(resp.value),
  99                         (char *)&resp.value);
 100}
 101
 102static ssize_t version_show(struct device *dev, struct device_attribute *attr,
 103                          char *buf)
 104{
 105        return get_info(dev, buf, CMD_GET_EC_LABEL);
 106}
 107
 108static DEVICE_ATTR_RO(version);
 109
 110static ssize_t build_revision_show(struct device *dev,
 111                                   struct device_attribute *attr, char *buf)
 112{
 113        return get_info(dev, buf, CMD_GET_EC_REV);
 114}
 115
 116static DEVICE_ATTR_RO(build_revision);
 117
 118static ssize_t build_date_show(struct device *dev,
 119                               struct device_attribute *attr, char *buf)
 120{
 121        return get_info(dev, buf, CMD_GET_EC_BUILD_DATE);
 122}
 123
 124static DEVICE_ATTR_RO(build_date);
 125
 126static ssize_t model_number_show(struct device *dev,
 127                                 struct device_attribute *attr, char *buf)
 128{
 129        return get_info(dev, buf, CMD_GET_EC_MODEL);
 130}
 131
 132static DEVICE_ATTR_RO(model_number);
 133
 134
 135static struct attribute *wilco_dev_attrs[] = {
 136        &dev_attr_boot_on_ac.attr,
 137        &dev_attr_build_date.attr,
 138        &dev_attr_build_revision.attr,
 139        &dev_attr_model_number.attr,
 140        &dev_attr_version.attr,
 141        NULL,
 142};
 143
 144static struct attribute_group wilco_dev_attr_group = {
 145        .attrs = wilco_dev_attrs,
 146};
 147
 148int wilco_ec_add_sysfs(struct wilco_ec_device *ec)
 149{
 150        return sysfs_create_group(&ec->dev->kobj, &wilco_dev_attr_group);
 151}
 152
 153void wilco_ec_remove_sysfs(struct wilco_ec_device *ec)
 154{
 155        sysfs_remove_group(&ec->dev->kobj, &wilco_dev_attr_group);
 156}
 157