136 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2019 Google LLC4 */5 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 <linux/unaligned.h>12 13/* Operation code; what the EC should do with the property */14enum ec_property_op {15 EC_OP_GET = 0,16 EC_OP_SET = 1,17};18 19struct 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;25 26struct 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;33 34static int send_property_msg(struct wilco_ec_device *ec,35 struct ec_property_request *rq,36 struct ec_property_response *rs)37{38 struct wilco_ec_message ec_msg;39 int ret;40 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);47 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;55 56 return 0;57}58 59int wilco_ec_get_property(struct wilco_ec_device *ec,60 struct wilco_ec_property_msg *prop_msg)61{62 struct ec_property_request rq;63 struct ec_property_response rs;64 int ret;65 66 memset(&rq, 0, sizeof(rq));67 rq.op = EC_OP_GET;68 put_unaligned_le32(prop_msg->property_id, rq.property_id);69 70 ret = send_property_msg(ec, &rq, &rs);71 if (ret < 0)72 return ret;73 74 prop_msg->length = rs.length;75 memcpy(prop_msg->data, rs.data, rs.length);76 77 return 0;78}79EXPORT_SYMBOL_GPL(wilco_ec_get_property);80 81int wilco_ec_set_property(struct wilco_ec_device *ec,82 struct wilco_ec_property_msg *prop_msg)83{84 struct ec_property_request rq;85 struct ec_property_response rs;86 int ret;87 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);93 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;99 100 return 0;101}102EXPORT_SYMBOL_GPL(wilco_ec_set_property);103 104int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id,105 u8 *val)106{107 struct wilco_ec_property_msg msg;108 int ret;109 110 msg.property_id = property_id;111 112 ret = wilco_ec_get_property(ec, &msg);113 if (ret < 0)114 return ret;115 if (msg.length != 1)116 return -EBADMSG;117 118 *val = msg.data[0];119 120 return 0;121}122EXPORT_SYMBOL_GPL(wilco_ec_get_byte_property);123 124int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id,125 u8 val)126{127 struct wilco_ec_property_msg msg;128 129 msg.property_id = property_id;130 msg.data[0] = val;131 msg.length = 1;132 133 return wilco_ec_set_property(ec, &msg);134}135EXPORT_SYMBOL_GPL(wilco_ec_set_byte_property);136