brintos

brintos / linux-shallow public Read only

0
0
Text · 5.5 KiB · d44c435 Raw
251 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2019 Google LLC4 *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/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>17 18#define CMD_KB_CMOS			0x7C19#define SUB_CMD_KB_CMOS_AUTO_ON		0x0320 21struct boot_on_ac_request {22	u8 cmd;			/* Always CMD_KB_CMOS */23	u8 reserved1;24	u8 sub_cmd;		/* Always SUB_CMD_KB_CMOS_AUTO_ON */25	u8 reserved3to5[3];26	u8 val;			/* Either 0 or 1 */27	u8 reserved7;28} __packed;29 30#define CMD_USB_CHARGE 0x3931 32enum usb_charge_op {33	USB_CHARGE_GET = 0,34	USB_CHARGE_SET = 1,35};36 37struct usb_charge_request {38	u8 cmd;		/* Always CMD_USB_CHARGE */39	u8 reserved;40	u8 op;		/* One of enum usb_charge_op */41	u8 val;		/* When setting, either 0 or 1 */42} __packed;43 44struct usb_charge_response {45	u8 reserved;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 */48} __packed;49 50#define CMD_EC_INFO			0x3851enum get_ec_info_op {52	CMD_GET_EC_LABEL	= 0,53	CMD_GET_EC_REV		= 1,54	CMD_GET_EC_MODEL	= 2,55	CMD_GET_EC_BUILD_DATE	= 3,56};57 58struct get_ec_info_req {59	u8 cmd;			/* Always CMD_EC_INFO */60	u8 reserved;61	u8 op;			/* One of enum get_ec_info_op */62} __packed;63 64struct get_ec_info_resp {65	u8 reserved[2];66	char value[9]; /* __nonstring: might not be null terminated */67} __packed;68 69static ssize_t boot_on_ac_store(struct device *dev,70				struct device_attribute *attr,71				const char *buf, size_t count)72{73	struct wilco_ec_device *ec = dev_get_drvdata(dev);74	struct boot_on_ac_request rq;75	struct wilco_ec_message msg;76	int ret;77	u8 val;78 79	ret = kstrtou8(buf, 10, &val);80	if (ret < 0)81		return ret;82	if (val > 1)83		return -EINVAL;84 85	memset(&rq, 0, sizeof(rq));86	rq.cmd = CMD_KB_CMOS;87	rq.sub_cmd = SUB_CMD_KB_CMOS_AUTO_ON;88	rq.val = val;89 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);95	if (ret < 0)96		return ret;97 98	return count;99}100 101static DEVICE_ATTR_WO(boot_on_ac);102 103static ssize_t get_info(struct device *dev, char *buf, enum get_ec_info_op op)104{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;108	int ret;109 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),116	};117 118	ret = wilco_ec_mailbox(ec, &msg);119	if (ret < 0)120		return ret;121 122	return sysfs_emit(buf, "%.*s\n", (int)sizeof(resp.value), (char *)&resp.value);123}124 125static ssize_t version_show(struct device *dev, struct device_attribute *attr,126			  char *buf)127{128	return get_info(dev, buf, CMD_GET_EC_LABEL);129}130 131static DEVICE_ATTR_RO(version);132 133static ssize_t build_revision_show(struct device *dev,134				   struct device_attribute *attr, char *buf)135{136	return get_info(dev, buf, CMD_GET_EC_REV);137}138 139static DEVICE_ATTR_RO(build_revision);140 141static ssize_t build_date_show(struct device *dev,142			       struct device_attribute *attr, char *buf)143{144	return get_info(dev, buf, CMD_GET_EC_BUILD_DATE);145}146 147static DEVICE_ATTR_RO(build_date);148 149static ssize_t model_number_show(struct device *dev,150				 struct device_attribute *attr, char *buf)151{152	return get_info(dev, buf, CMD_GET_EC_MODEL);153}154 155static DEVICE_ATTR_RO(model_number);156 157static int send_usb_charge(struct wilco_ec_device *ec,158				struct usb_charge_request *rq,159				struct usb_charge_response *rs)160{161	struct wilco_ec_message msg;162	int ret;163 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);171	if (ret < 0)172		return ret;173	if (rs->status)174		return -EIO;175 176	return 0;177}178 179static ssize_t usb_charge_show(struct device *dev,180				    struct device_attribute *attr, char *buf)181{182	struct wilco_ec_device *ec = dev_get_drvdata(dev);183	struct usb_charge_request rq;184	struct usb_charge_response rs;185	int ret;186 187	memset(&rq, 0, sizeof(rq));188	rq.cmd = CMD_USB_CHARGE;189	rq.op = USB_CHARGE_GET;190 191	ret = send_usb_charge(ec, &rq, &rs);192	if (ret < 0)193		return ret;194 195	return sysfs_emit(buf, "%d\n", rs.val);196}197 198static ssize_t usb_charge_store(struct device *dev,199				     struct device_attribute *attr,200				     const char *buf, size_t count)201{202	struct wilco_ec_device *ec = dev_get_drvdata(dev);203	struct usb_charge_request rq;204	struct usb_charge_response rs;205	int ret;206	u8 val;207 208	ret = kstrtou8(buf, 10, &val);209	if (ret < 0)210		return ret;211	if (val > 1)212		return -EINVAL;213 214	memset(&rq, 0, sizeof(rq));215	rq.cmd = CMD_USB_CHARGE;216	rq.op = USB_CHARGE_SET;217	rq.val = val;218 219	ret = send_usb_charge(ec, &rq, &rs);220	if (ret < 0)221		return ret;222 223	return count;224}225 226static DEVICE_ATTR_RW(usb_charge);227 228static 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,235	NULL,236};237 238static const struct attribute_group wilco_dev_attr_group = {239	.attrs = wilco_dev_attrs,240};241 242int wilco_ec_add_sysfs(struct wilco_ec_device *ec)243{244	return sysfs_create_group(&ec->dev->kobj, &wilco_dev_attr_group);245}246 247void wilco_ec_remove_sysfs(struct wilco_ec_device *ec)248{249	sysfs_remove_group(&ec->dev->kobj, &wilco_dev_attr_group);250}251