brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · 9951c8d Raw
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