Merge tag 'regmap-fix-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux/fpc-iii.git] / drivers / platform / chrome / wilco_ec / properties.c
blobc2bf4c95c5d2c981bab6ae2f562713bd80c40f3f
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright 2019 Google LLC
4 */
6 #include <linux/errno.h>
7 #include <linux/export.h>
8 #include <linux/platform_data/wilco-ec.h>
9 #include <linux/string.h>
10 #include <linux/types.h>
11 #include <asm/unaligned.h>
13 /* Operation code; what the EC should do with the property */
14 enum ec_property_op {
15 EC_OP_GET = 0,
16 EC_OP_SET = 1,
19 struct ec_property_request {
20 u8 op; /* One of enum ec_property_op */
21 u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
22 u8 length;
23 u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
24 } __packed;
26 struct ec_property_response {
27 u8 reserved[2];
28 u8 op; /* One of enum ec_property_op */
29 u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
30 u8 length;
31 u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
32 } __packed;
34 static int send_property_msg(struct wilco_ec_device *ec,
35 struct ec_property_request *rq,
36 struct ec_property_response *rs)
38 struct wilco_ec_message ec_msg;
39 int ret;
41 memset(&ec_msg, 0, sizeof(ec_msg));
42 ec_msg.type = WILCO_EC_MSG_PROPERTY;
43 ec_msg.request_data = rq;
44 ec_msg.request_size = sizeof(*rq);
45 ec_msg.response_data = rs;
46 ec_msg.response_size = sizeof(*rs);
48 ret = wilco_ec_mailbox(ec, &ec_msg);
49 if (ret < 0)
50 return ret;
51 if (rs->op != rq->op)
52 return -EBADMSG;
53 if (memcmp(rq->property_id, rs->property_id, sizeof(rs->property_id)))
54 return -EBADMSG;
56 return 0;
59 int wilco_ec_get_property(struct wilco_ec_device *ec,
60 struct wilco_ec_property_msg *prop_msg)
62 struct ec_property_request rq;
63 struct ec_property_response rs;
64 int ret;
66 memset(&rq, 0, sizeof(rq));
67 rq.op = EC_OP_GET;
68 put_unaligned_le32(prop_msg->property_id, rq.property_id);
70 ret = send_property_msg(ec, &rq, &rs);
71 if (ret < 0)
72 return ret;
74 prop_msg->length = rs.length;
75 memcpy(prop_msg->data, rs.data, rs.length);
77 return 0;
79 EXPORT_SYMBOL_GPL(wilco_ec_get_property);
81 int wilco_ec_set_property(struct wilco_ec_device *ec,
82 struct wilco_ec_property_msg *prop_msg)
84 struct ec_property_request rq;
85 struct ec_property_response rs;
86 int ret;
88 memset(&rq, 0, sizeof(rq));
89 rq.op = EC_OP_SET;
90 put_unaligned_le32(prop_msg->property_id, rq.property_id);
91 rq.length = prop_msg->length;
92 memcpy(rq.data, prop_msg->data, prop_msg->length);
94 ret = send_property_msg(ec, &rq, &rs);
95 if (ret < 0)
96 return ret;
97 if (rs.length != prop_msg->length)
98 return -EBADMSG;
100 return 0;
102 EXPORT_SYMBOL_GPL(wilco_ec_set_property);
104 int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id,
105 u8 *val)
107 struct wilco_ec_property_msg msg;
108 int ret;
110 msg.property_id = property_id;
112 ret = wilco_ec_get_property(ec, &msg);
113 if (ret < 0)
114 return ret;
115 if (msg.length != 1)
116 return -EBADMSG;
118 *val = msg.data[0];
120 return 0;
122 EXPORT_SYMBOL_GPL(wilco_ec_get_byte_property);
124 int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id,
125 u8 val)
127 struct wilco_ec_property_msg msg;
129 msg.property_id = property_id;
130 msg.data[0] = val;
131 msg.length = 1;
133 return wilco_ec_set_property(ec, &msg);
135 EXPORT_SYMBOL_GPL(wilco_ec_set_byte_property);