Loading...
Note: File does not exist in v4.6.
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2019 Google LLC
4 */
5
6#include <linux/platform_data/wilco-ec.h>
7#include <linux/string.h>
8#include <linux/unaligned/le_memmove.h>
9
10/* Operation code; what the EC should do with the property */
11enum ec_property_op {
12 EC_OP_GET = 0,
13 EC_OP_SET = 1,
14};
15
16struct ec_property_request {
17 u8 op; /* One of enum ec_property_op */
18 u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
19 u8 length;
20 u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
21} __packed;
22
23struct ec_property_response {
24 u8 reserved[2];
25 u8 op; /* One of enum ec_property_op */
26 u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
27 u8 length;
28 u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
29} __packed;
30
31static int send_property_msg(struct wilco_ec_device *ec,
32 struct ec_property_request *rq,
33 struct ec_property_response *rs)
34{
35 struct wilco_ec_message ec_msg;
36 int ret;
37
38 memset(&ec_msg, 0, sizeof(ec_msg));
39 ec_msg.type = WILCO_EC_MSG_PROPERTY;
40 ec_msg.request_data = rq;
41 ec_msg.request_size = sizeof(*rq);
42 ec_msg.response_data = rs;
43 ec_msg.response_size = sizeof(*rs);
44
45 ret = wilco_ec_mailbox(ec, &ec_msg);
46 if (ret < 0)
47 return ret;
48 if (rs->op != rq->op)
49 return -EBADMSG;
50 if (memcmp(rq->property_id, rs->property_id, sizeof(rs->property_id)))
51 return -EBADMSG;
52
53 return 0;
54}
55
56int wilco_ec_get_property(struct wilco_ec_device *ec,
57 struct wilco_ec_property_msg *prop_msg)
58{
59 struct ec_property_request rq;
60 struct ec_property_response rs;
61 int ret;
62
63 memset(&rq, 0, sizeof(rq));
64 rq.op = EC_OP_GET;
65 put_unaligned_le32(prop_msg->property_id, rq.property_id);
66
67 ret = send_property_msg(ec, &rq, &rs);
68 if (ret < 0)
69 return ret;
70
71 prop_msg->length = rs.length;
72 memcpy(prop_msg->data, rs.data, rs.length);
73
74 return 0;
75}
76EXPORT_SYMBOL_GPL(wilco_ec_get_property);
77
78int wilco_ec_set_property(struct wilco_ec_device *ec,
79 struct wilco_ec_property_msg *prop_msg)
80{
81 struct ec_property_request rq;
82 struct ec_property_response rs;
83 int ret;
84
85 memset(&rq, 0, sizeof(rq));
86 rq.op = EC_OP_SET;
87 put_unaligned_le32(prop_msg->property_id, rq.property_id);
88 rq.length = prop_msg->length;
89 memcpy(rq.data, prop_msg->data, prop_msg->length);
90
91 ret = send_property_msg(ec, &rq, &rs);
92 if (ret < 0)
93 return ret;
94 if (rs.length != prop_msg->length)
95 return -EBADMSG;
96
97 return 0;
98}
99EXPORT_SYMBOL_GPL(wilco_ec_set_property);
100
101int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id,
102 u8 *val)
103{
104 struct wilco_ec_property_msg msg;
105 int ret;
106
107 msg.property_id = property_id;
108
109 ret = wilco_ec_get_property(ec, &msg);
110 if (ret < 0)
111 return ret;
112 if (msg.length != 1)
113 return -EBADMSG;
114
115 *val = msg.data[0];
116
117 return 0;
118}
119EXPORT_SYMBOL_GPL(wilco_ec_get_byte_property);
120
121int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id,
122 u8 val)
123{
124 struct wilco_ec_property_msg msg;
125
126 msg.property_id = property_id;
127 msg.data[0] = val;
128 msg.length = 1;
129
130 return wilco_ec_set_property(ec, &msg);
131}
132EXPORT_SYMBOL_GPL(wilco_ec_set_byte_property);