Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2019 Google LLC
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 /* Operation code; what the EC should do with the property */
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; /* One of enum ec_property_op */
0021     u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
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; /* One of enum ec_property_op */
0029     u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
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);