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 sysfs_emit(buf
, "%.*s\n", (int)sizeof(resp
.value
), (char *)&resp
.value
);
125 static ssize_t
version_show(struct device
*dev
, struct device_attribute
*attr
,
128 return get_info(dev
, buf
, CMD_GET_EC_LABEL
);
131 static DEVICE_ATTR_RO(version
);
133 static ssize_t
build_revision_show(struct device
*dev
,
134 struct device_attribute
*attr
, char *buf
)
136 return get_info(dev
, buf
, CMD_GET_EC_REV
);
139 static DEVICE_ATTR_RO(build_revision
);
141 static ssize_t
build_date_show(struct device
*dev
,
142 struct device_attribute
*attr
, char *buf
)
144 return get_info(dev
, buf
, CMD_GET_EC_BUILD_DATE
);
147 static DEVICE_ATTR_RO(build_date
);
149 static ssize_t
model_number_show(struct device
*dev
,
150 struct device_attribute
*attr
, char *buf
)
152 return get_info(dev
, buf
, CMD_GET_EC_MODEL
);
155 static DEVICE_ATTR_RO(model_number
);
157 static int send_usb_charge(struct wilco_ec_device
*ec
,
158 struct usb_charge_request
*rq
,
159 struct usb_charge_response
*rs
)
161 struct wilco_ec_message msg
;
164 memset(&msg
, 0, sizeof(msg
));
165 msg
.type
= WILCO_EC_MSG_LEGACY
;
166 msg
.request_data
= rq
;
167 msg
.request_size
= sizeof(*rq
);
168 msg
.response_data
= rs
;
169 msg
.response_size
= sizeof(*rs
);
170 ret
= wilco_ec_mailbox(ec
, &msg
);
179 static ssize_t
usb_charge_show(struct device
*dev
,
180 struct device_attribute
*attr
, char *buf
)
182 struct wilco_ec_device
*ec
= dev_get_drvdata(dev
);
183 struct usb_charge_request rq
;
184 struct usb_charge_response rs
;
187 memset(&rq
, 0, sizeof(rq
));
188 rq
.cmd
= CMD_USB_CHARGE
;
189 rq
.op
= USB_CHARGE_GET
;
191 ret
= send_usb_charge(ec
, &rq
, &rs
);
195 return sysfs_emit(buf
, "%d\n", rs
.val
);
198 static ssize_t
usb_charge_store(struct device
*dev
,
199 struct device_attribute
*attr
,
200 const char *buf
, size_t count
)
202 struct wilco_ec_device
*ec
= dev_get_drvdata(dev
);
203 struct usb_charge_request rq
;
204 struct usb_charge_response rs
;
208 ret
= kstrtou8(buf
, 10, &val
);
214 memset(&rq
, 0, sizeof(rq
));
215 rq
.cmd
= CMD_USB_CHARGE
;
216 rq
.op
= USB_CHARGE_SET
;
219 ret
= send_usb_charge(ec
, &rq
, &rs
);
226 static DEVICE_ATTR_RW(usb_charge
);
228 static struct attribute
*wilco_dev_attrs
[] = {
229 &dev_attr_boot_on_ac
.attr
,
230 &dev_attr_build_date
.attr
,
231 &dev_attr_build_revision
.attr
,
232 &dev_attr_model_number
.attr
,
233 &dev_attr_usb_charge
.attr
,
234 &dev_attr_version
.attr
,
238 static const struct attribute_group wilco_dev_attr_group
= {
239 .attrs
= wilco_dev_attrs
,
242 int wilco_ec_add_sysfs(struct wilco_ec_device
*ec
)
244 return sysfs_create_group(&ec
->dev
->kobj
, &wilco_dev_attr_group
);
247 void wilco_ec_remove_sysfs(struct wilco_ec_device
*ec
)
249 sysfs_remove_group(&ec
->dev
->kobj
, &wilco_dev_attr_group
);