0001
0002
0003
0004
0005
0006 #include <linux/errno.h>
0007 #include <linux/export.h>
0008 #include <linux/platform_data/wilco-ec.h>
0009 #include <linux/string.h>
0010 #include <linux/types.h>
0011 #include <asm/unaligned.h>
0012
0013
0014 enum ec_property_op {
0015 EC_OP_GET = 0,
0016 EC_OP_SET = 1,
0017 };
0018
0019 struct ec_property_request {
0020 u8 op;
0021 u8 property_id[4];
0022 u8 length;
0023 u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
0024 } __packed;
0025
0026 struct ec_property_response {
0027 u8 reserved[2];
0028 u8 op;
0029 u8 property_id[4];
0030 u8 length;
0031 u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
0032 } __packed;
0033
0034 static int send_property_msg(struct wilco_ec_device *ec,
0035 struct ec_property_request *rq,
0036 struct ec_property_response *rs)
0037 {
0038 struct wilco_ec_message ec_msg;
0039 int ret;
0040
0041 memset(&ec_msg, 0, sizeof(ec_msg));
0042 ec_msg.type = WILCO_EC_MSG_PROPERTY;
0043 ec_msg.request_data = rq;
0044 ec_msg.request_size = sizeof(*rq);
0045 ec_msg.response_data = rs;
0046 ec_msg.response_size = sizeof(*rs);
0047
0048 ret = wilco_ec_mailbox(ec, &ec_msg);
0049 if (ret < 0)
0050 return ret;
0051 if (rs->op != rq->op)
0052 return -EBADMSG;
0053 if (memcmp(rq->property_id, rs->property_id, sizeof(rs->property_id)))
0054 return -EBADMSG;
0055
0056 return 0;
0057 }
0058
0059 int wilco_ec_get_property(struct wilco_ec_device *ec,
0060 struct wilco_ec_property_msg *prop_msg)
0061 {
0062 struct ec_property_request rq;
0063 struct ec_property_response rs;
0064 int ret;
0065
0066 memset(&rq, 0, sizeof(rq));
0067 rq.op = EC_OP_GET;
0068 put_unaligned_le32(prop_msg->property_id, rq.property_id);
0069
0070 ret = send_property_msg(ec, &rq, &rs);
0071 if (ret < 0)
0072 return ret;
0073
0074 prop_msg->length = rs.length;
0075 memcpy(prop_msg->data, rs.data, rs.length);
0076
0077 return 0;
0078 }
0079 EXPORT_SYMBOL_GPL(wilco_ec_get_property);
0080
0081 int wilco_ec_set_property(struct wilco_ec_device *ec,
0082 struct wilco_ec_property_msg *prop_msg)
0083 {
0084 struct ec_property_request rq;
0085 struct ec_property_response rs;
0086 int ret;
0087
0088 memset(&rq, 0, sizeof(rq));
0089 rq.op = EC_OP_SET;
0090 put_unaligned_le32(prop_msg->property_id, rq.property_id);
0091 rq.length = prop_msg->length;
0092 memcpy(rq.data, prop_msg->data, prop_msg->length);
0093
0094 ret = send_property_msg(ec, &rq, &rs);
0095 if (ret < 0)
0096 return ret;
0097 if (rs.length != prop_msg->length)
0098 return -EBADMSG;
0099
0100 return 0;
0101 }
0102 EXPORT_SYMBOL_GPL(wilco_ec_set_property);
0103
0104 int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id,
0105 u8 *val)
0106 {
0107 struct wilco_ec_property_msg msg;
0108 int ret;
0109
0110 msg.property_id = property_id;
0111
0112 ret = wilco_ec_get_property(ec, &msg);
0113 if (ret < 0)
0114 return ret;
0115 if (msg.length != 1)
0116 return -EBADMSG;
0117
0118 *val = msg.data[0];
0119
0120 return 0;
0121 }
0122 EXPORT_SYMBOL_GPL(wilco_ec_get_byte_property);
0123
0124 int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id,
0125 u8 val)
0126 {
0127 struct wilco_ec_property_msg msg;
0128
0129 msg.property_id = property_id;
0130 msg.data[0] = val;
0131 msg.length = 1;
0132
0133 return wilco_ec_set_property(ec, &msg);
0134 }
0135 EXPORT_SYMBOL_GPL(wilco_ec_set_byte_property);