1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2019 Google LLC
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/
8 * See Documentation/ABI/testing/sysfs-platform-wilco-ec for more information.
11 #include <linux/device.h>
12 #include <linux/kernel.h>
13 #include <linux/platform_data/wilco-ec.h>
14 #include <linux/string.h>
15 #include <linux/sysfs.h>
16 #include <linux/types.h>
18 #define CMD_KB_CMOS 0x7C
19 #define SUB_CMD_KB_CMOS_AUTO_ON 0x03
21 struct boot_on_ac_request
{
22 u8 cmd
; /* Always CMD_KB_CMOS */
24 u8 sub_cmd
; /* Always SUB_CMD_KB_CMOS_AUTO_ON */
26 u8 val
; /* Either 0 or 1 */
30 #define CMD_USB_CHARGE 0x39
37 struct usb_charge_request
{
38 u8 cmd
; /* Always CMD_USB_CHARGE */
40 u8 op
; /* One of enum usb_charge_op */
41 u8 val
; /* When setting, either 0 or 1 */
44 struct usb_charge_response
{
46 u8 status
; /* Set by EC to 0 on success, other value on failure */
47 u8 val
; /* When getting, set by EC to either 0 or 1 */
50 #define CMD_EC_INFO 0x38
55 CMD_GET_EC_BUILD_DATE
= 3,
58 struct get_ec_info_req
{
59 u8 cmd
; /* Always CMD_EC_INFO */
61 u8 op
; /* One of enum get_ec_info_op */
64 struct get_ec_info_resp
{
66 char value
[9]; /* __nonstring: might not be null terminated */
69 static ssize_t
boot_on_ac_store(struct device
*dev
,
70 struct device_attribute
*attr
,
71 const char *buf
, size_t count
)
73 struct wilco_ec_device
*ec
= dev_get_drvdata(dev
);
74 struct boot_on_ac_request rq
;
75 struct wilco_ec_message msg
;
79 ret
= kstrtou8(buf
, 10, &val
);
85 memset(&rq
, 0, sizeof(rq
));
87 rq
.sub_cmd
= SUB_CMD_KB_CMOS_AUTO_ON
;
90 memset(&msg
, 0, sizeof(msg
));
91 msg
.type
= WILCO_EC_MSG_LEGACY
;
92 msg
.request_data
= &rq
;
93 msg
.request_size
= sizeof(rq
);
94 ret
= wilco_ec_mailbox(ec
, &msg
);
101 static DEVICE_ATTR_WO(boot_on_ac
);
103 static ssize_t
get_info(struct device
*dev
, char *buf
, enum get_ec_info_op op
)
105 struct wilco_ec_device
*ec
= dev_get_drvdata(dev
);
106 struct get_ec_info_req req
= { .cmd
= CMD_EC_INFO
, .op
= op
};
107 struct get_ec_info_resp resp
;
110 struct wilco_ec_message msg
= {
111 .type
= WILCO_EC_MSG_LEGACY
,
112 .request_data
= &req
,
113 .request_size
= sizeof(req
),
114 .response_data
= &resp
,
115 .response_size
= sizeof(resp
),
118 ret
= wilco_ec_mailbox(ec
, &msg
);
122 return scnprintf(buf
, PAGE_SIZE
, "%.*s\n", (int)sizeof(resp
.value
),
123 (char *)&resp
.value
);
126 static ssize_t
version_show(struct device
*dev
, struct device_attribute
*attr
,
129 return get_info(dev
, buf
, CMD_GET_EC_LABEL
);
132 static DEVICE_ATTR_RO(version
);
134 static ssize_t
build_revision_show(struct device
*dev
,
135 struct device_attribute
*attr
, char *buf
)
137 return get_info(dev
, buf
, CMD_GET_EC_REV
);
140 static DEVICE_ATTR_RO(build_revision
);
142 static ssize_t
build_date_show(struct device
*dev
,
143 struct device_attribute
*attr
, char *buf
)
145 return get_info(dev
, buf
, CMD_GET_EC_BUILD_DATE
);
148 static DEVICE_ATTR_RO(build_date
);
150 static ssize_t
model_number_show(struct device
*dev
,
151 struct device_attribute
*attr
, char *buf
)
153 return get_info(dev
, buf
, CMD_GET_EC_MODEL
);
156 static DEVICE_ATTR_RO(model_number
);
158 static int send_usb_charge(struct wilco_ec_device
*ec
,
159 struct usb_charge_request
*rq
,
160 struct usb_charge_response
*rs
)
162 struct wilco_ec_message msg
;
165 memset(&msg
, 0, sizeof(msg
));
166 msg
.type
= WILCO_EC_MSG_LEGACY
;
167 msg
.request_data
= rq
;
168 msg
.request_size
= sizeof(*rq
);
169 msg
.response_data
= rs
;
170 msg
.response_size
= sizeof(*rs
);
171 ret
= wilco_ec_mailbox(ec
, &msg
);
180 static ssize_t
usb_charge_show(struct device
*dev
,
181 struct device_attribute
*attr
, char *buf
)
183 struct wilco_ec_device
*ec
= dev_get_drvdata(dev
);
184 struct usb_charge_request rq
;
185 struct usb_charge_response rs
;
188 memset(&rq
, 0, sizeof(rq
));
189 rq
.cmd
= CMD_USB_CHARGE
;
190 rq
.op
= USB_CHARGE_GET
;
192 ret
= send_usb_charge(ec
, &rq
, &rs
);
196 return sprintf(buf
, "%d\n", rs
.val
);
199 static ssize_t
usb_charge_store(struct device
*dev
,
200 struct device_attribute
*attr
,
201 const char *buf
, size_t count
)
203 struct wilco_ec_device
*ec
= dev_get_drvdata(dev
);
204 struct usb_charge_request rq
;
205 struct usb_charge_response rs
;
209 ret
= kstrtou8(buf
, 10, &val
);
215 memset(&rq
, 0, sizeof(rq
));
216 rq
.cmd
= CMD_USB_CHARGE
;
217 rq
.op
= USB_CHARGE_SET
;
220 ret
= send_usb_charge(ec
, &rq
, &rs
);
227 static DEVICE_ATTR_RW(usb_charge
);
229 static struct attribute
*wilco_dev_attrs
[] = {
230 &dev_attr_boot_on_ac
.attr
,
231 &dev_attr_build_date
.attr
,
232 &dev_attr_build_revision
.attr
,
233 &dev_attr_model_number
.attr
,
234 &dev_attr_usb_charge
.attr
,
235 &dev_attr_version
.attr
,
239 static struct attribute_group wilco_dev_attr_group
= {
240 .attrs
= wilco_dev_attrs
,
243 int wilco_ec_add_sysfs(struct wilco_ec_device
*ec
)
245 return sysfs_create_group(&ec
->dev
->kobj
, &wilco_dev_attr_group
);
248 void wilco_ec_remove_sysfs(struct wilco_ec_device
*ec
)
250 sysfs_remove_group(&ec
->dev
->kobj
, &wilco_dev_attr_group
);